我对单元测试和整体TDD都很陌生。
我的服务层(WCF)中有以下Login方法,该方法作为Windows服务托管。我的服务层遵循Facade模式,所有对服务层的调用都是使用请求对象进行的,并返回相应的响应对象。
public LoginResponse Login(LoginRequest request)
{
var response = new LoginResponse(request.RequestId);
try
{
if (!ValidRequest(request, response, Validate.ClientTag))
return response;
var user = userDao.GetByUserId(request.UserId);
if (user != null)
{
if (request.Password != "")
{
var authenticationService = new AuthenticationService();
if (authenticationService.Authenticate(user, request.Password))
{
return response;
}
response.ErrorCode = "IncorrectPassword";
}
else
{
response.ErrorCode = "PasswordNotFound";
}
}
else
{
response.ErrorCode = "UserNotFound";
}
response.Acknowledge = AcknowledgeType.Failure;
return response;
}
catch (Exception ex)
{
Log.Error(ex);
response.Acknowledge = AcknowledgeType.Failure;
response.ErrorCode = "Exception";
return response;
}
}
这两行:
userDao.GetByUserId(request.UserId);
和
authenticationService.Authenticate(user, request.Password);
正在调用数据库。
这是我用xUnit和JustMock编写的测试:
[Theory]
[InlineData("manager", "manager")]
public void LoginTest(string userId, string password)
{
//Arrange
var userServiceMock = Mock.Create<IUserManagementService>();
var request = new LoginRequest().Prepare();
request.UserId = userId;
request.Password = password;
var response = new LoginResponse(request.RequestId);
Mock.Arrange(() => userServiceMock.Login(request)).Returns(response).OccursOnce();
//Act
userServiceMock.Login(request);
//Assert
Mock.Assert(userServiceMock);
}
即使我已将服务方法更改为
,我遇到的问题仍然存在public LoginResponse Login(LoginRequest request)
{
return null;
}
我的测试仍然通过。我做错了什么?
答案 0 :(得分:3)
你没有测试任何东西。你正在嘲笑你的系统,这是不正确的。
有关模拟的简要说明,请参阅this answer。
如果您要测试UserManagementService.Login()
,则需要:
[Theory]
[InlineData("manager", "manager")]
public void LoginTest(string userId, string password)
{
// Arrange
// System under test
IUserManagementService userService = new UserManagementService();
var request = new LoginRequest().Prepare();
request.UserId = userId;
request.Password = password;
var expectedResponse = new LoginResponse(request.RequestId);
//Act
var actualResponse = userService.Login(request);
//Assert
Assert.AreEqual(actualResponse.Something, expectedResponse.Something);
}
无需嘲笑任何东西。 (如果您不希望单元测试写入Login()
,AuthenticationService
,userDao
甚至Log
,您可能需要模拟{{1}}所具有的所有依赖项。日志。)
答案 1 :(得分:3)
您已经模拟了要测试的课程。当您在Login
上致电userServiceMock
时,以下代码行是相关的:
Mock.Arrange(() => userServiceMock.Login(request)).Returns(response).OccursOnce();
也就是说,您总是返回有效的结果。实际的代码永远不会被执行。
每个单元测试都有一个正在测试的系统&#34; (SUT)。你永远不会想要嘲笑SUT本身。您只能模拟SUT所依赖的任何其他对象。在您的情况下,UserService
似乎是您的SUT。没有理由模仿用户服务,你想测试真实的用户服务!
然而,SUT似乎使用UserDao
,这可能是在某处注入的。注入UserDAO的模拟而不是真实的模拟。
此外,它使用AuthenticationService
。不幸的是它没有注入,但你的方法动态创建一个实例。这使得无法使用它的模拟实现。您需要重构UserService,以便注入要使用的AuthenticationService
。然后你的单元测试可以注入模拟AuthenticationService
。