这是Moq 框架的一个很好的示例用例。例如,当您提请注意进行远程调用时,应该模拟该服务。理想情况下,您应该尝试模拟不同的变量方面,以便您可以轻松且一致地提供一组已知的输入来验证预期的一组输出。由于您没有提供任何源代码,我将做一些假设——分享一些示例代码和相应的单元测试。
public class LoginResult
{
public string RedirectUrl { get; set; }
public string FailureMsg { get; set; }
public MonkeyBusiness AuthToken { get; set; }
}
[
HttpPost,
AllowAnonymous,
Route("api/[controller]/login")
]
public async Task<LoginResult> Login(
[FromBody] CredentialsModel credentials,
[FromServices] ILogger logger,
[FromServices] IAuthenticationModule authentication,
[FromServices] IAuthClaimsPrincipalBuiler claimsPrincipalBuilder)
{
try
{
var result =
await authentication.ExternalAuthenticateAsync(credentials);
if (result.IsAuthenticated)
{
var principal =
await claimsPrincipalBuilder.BuildAsync(credentials);
await HttpContext.Authentication.SignInAsync("Scheme", principal);
return new LoginResult
{
AuthToken =
"Too much source to make up just for stackoverflow, " +
"but I hope you now get the point..."
};
}
return new LoginResult { FailureMsg = "Invalid credentials." };
}
catch (Exception ex)
{
logger.LogError(ex.Message, ex);
return new LoginResult { FailureMsg = ex.Message };
}
}
然后您可以进行与此类似的单元测试,在其中模拟接口的特定实现。在这种情况下,您将模拟IAuthenticationModule 并进行多项测试,以确保无论远程服务器返回您的Login 逻辑如何都按期望/预期处理它。模拟async 的东西很容易做到。
using xUnit;
[Fact]
public async Task LoginThrowsAsExpectedTest()
{
// Arrange
var controller = new LoginController();
var loggerMock = new Mock<ILogger>();
var authModuleMock = new Mock<IAuthenticationModule>();
var expectedMessage = "I knew it!";
// Setup async methods!
authModuleMock.Setup(am => am.ExternalAuthenticateAsync(It.IsAny<CredentialsModel>())
.ThrowsAsync(new Exception(expectedMessage));
// Act
var result =
await controller.Login(
new CredentialsModel(),
loggerMock.Object,
authModuleMock.Object,
null);
// Assert
Assert.Equal(expectedMessage, result.FailureMsg);
}
或者您希望正确验证的一个。
using xUnit;
[Fact]
public async Task LoginHandlesIsNotAuthenticatedTest()
{
// Arrange
var controller = new LoginController();
var loggerMock = new Mock<ILogger>();
var authModuleMock = new Mock<IAuthenticationModule>();
var expectedMessage = "Invalid credentials.";
// Setup async methods!
authModuleMock.Setup(am => am.ExternalAuthenticateAsync(It.IsAny<CredentialsModel>())
.ReturnsAsync(new AuthResult { IsAuthenticated = false });
// Act
var result =
await controller.Login(
new CredentialsModel(),
loggerMock.Object,
authModuleMock.Object,
null);
// Assert
Assert.Equal(expectedMessage, result.FailureMsg);
}
关键是您仍然可以相当轻松地使用 Moq 编写 async 和 await 单元测试...