即使断言不正确,模拟和单元测试也会通过
本文关键字:单元测试 模拟 断言 不正确 | 更新日期: 2023-09-27 17:56:17
我对单元测试和TDD整体上很陌生。
我的服务层 (WCF) 中有以下登录方法,该方法作为 Windows 服务托管。我的服务层遵循外观模式,对服务层的所有调用都是使用请求对象进行的,并返回相应的响应对象。
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;
}
我的测试仍然通过。我做错了什么?
你没有测试任何东西。您正在模拟您正在模拟您的测试系统,这是不正确的。
请参阅此答案,了解什么是模拟的简要说明。
如果您正在测试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
。
你已经模拟了要测试的类。在 userServiceMock
上调用 Login
时,以下代码行是相关的:
Mock.Arrange(() => userServiceMock.Login(request)).Returns(response).OccursOnce();
也就是说,您始终返回有效的结果。实际代码永远不会执行。
每个单元测试都有一个"待测系统"(SUT)。你永远不会想嘲笑SUT本身。您只模拟 SUT 所依赖的任何其他对象。在您的情况下,UserService
似乎是您的 SUT。没有理由嘲笑用户服务,你想测试真正的服务!
然而,SUT似乎使用了一种可能被注入到某处的UserDao
。注入用户DAO的模拟而不是真实的模拟。
此外,它还使用AuthenticationService
。不幸的是,它没有注入,但您的方法会动态创建一个实例。这使得无法使用它的模拟实现。您将需要重构您的用户服务,以便您可以注入要使用的AuthenticationService
。然后你的单元测试可以注入AuthenticationService
的模拟。