免责声明:这是我第一次写单元测试......温柔! :)
我正在尝试为以下方法编写测试,并希望人们的想法是否我正在考虑这个正确的方法。我有一个名为IAuthenticationProvider的接口,使用以下方法:
bool Authenticate(string username, string password)
我还有一个名为UserAccountService的类,它具有以下方法:
bool SignIn(string username, string password)
UserAccountService将IAuthenticationProvider接口作为构造函数的一部分,并在SignIn方法中使用。 SignIn方法看起来有点像:
public bool SignIn(string username, string password)
{
// _provider is of type IAuthenticationProvider
bool result = _provider.Authenticate( username, password );
// ....
return result;
}
最初,当我想到“使用未知用户名登录”,“使用无效密码登录”等测试时,等等。但是,我开始认为我真的不想测试“身份验证”方面,即_provider.Authenticate,但我想测试实际的登录。所以,我认为测试,例如“登录时已经登录”,“当用户无法通过身份验证时登录”等等,会更有意义
这是接近这类测试的正确方法吗?
亲切的问候
迈克尔
答案 0 :(得分:2)
您可以使用基于模拟的测试。这将设置UserAccountService
,其模拟实现为IAuthenticationProvider
。
//happy case provider return true
mock = createMock(IAuthenticationProvider, true);
service = new UserAccountService(mock).SignIn(..);
...
//provider will return false
mock = createMock(IAuthenticationProvider, false);
service = new UserAccountService(mock).SignIn(..);
...
如果您愿意,可以编写自己的模拟实现。大多数情况下,使用模拟库作为easymock更容易:
//same as above
mock = createMock(IAuthenticationProvider.class)
expect(mock.Authenticate(...)).andReturn(true);
replay(mock)
service = new UserAccountService(mock).SignIn(..);
//test here
模拟测试有自己的成本,只应在无法进行基于状态的测试时使用。您的应用程序设计应该以类的形式依赖于尽可能少的类,并且理想情况下可以自己工作(加上运行时)。
答案 1 :(得分:1)
您在IAuthenticationProvider类的测试中测试身份验证。这被认为是有效的。在SignIn()中,您必须将_provider视为完美(任何问题都将在您的测试套件中的其他地方进行测试)并测试SignIn例程。
但是,您必须在SignIn方法上测试已经为IAuthProvider测试的所有内容。这将为您提供额外的保障,即您的信息实际上正确传递给_provider,并且其结果已正确返回。
答案 2 :(得分:0)
我同意您不应该在SignIn中对身份验证方面进行单元测试,因为这实际上发生在提供程序中。
如果所有SignIn方法正在执行的操作是上面显示的,返回_provider.Authenticate的结果,那么对该特定方法有意义的唯一测试非常简单,以验证它是否为False返回False来自_provider.Authenticate的_provider.Authenticate和True表示True。将具有已知结果的模拟提供程序传递给构造函数以进行测试。
如果“已登录时登录”和“当用户无法通过身份验证时登录”在您的SignIn方法中处理但未在上面显示,那么是的,在那里测试它们是有意义的。但如果他们在其他地方完成则不行。对于单元测试,您只想测试特定单元负责的内容。