我目前正在尝试学习单元测试,并且已经在ASP.NET Core中创建了项目,因此我可以在实际示例中学习测试。我想在API控制器中测试用于认证方法的快乐路径,因此它将返回OkObjectResult。
到目前为止我所拥有的。
我要测试的控制器方法
[AllowAnonymous]
[HttpPost("authenticate")]
public IActionResult Authenticate([FromBody]User userParam)
{
var user = _userService.Authenticate(userParam.Nickname,
userParam.Password).Result;
if(user == null)
{
return BadRequest(
new { message = "Username or password is incorrect " }
);
}
return Ok(user);
}
实现IUserService的类中的Authenticate方法:
public async Task<User> Authenticate(string nickname, string password)
{
var user = _repository.User.GetAllUsersAsync().Result.SingleOrDefault(u => u.Nickname == nickname && u.Password == password);
if(user == null)
{
return null;
}
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
var tokenDescription = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, user.UserId.ToString())
}),
Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescription);
user.Token = tokenHandler.WriteToken(token);
try
{
await _repository.User.UpdateUserAsync(user);
user.Password = null;
return user;
}
catch (Exception e)
{
return user;
}
}
我的单元测试:
[Fact]
public void Authenticate_WhenCalled_ReturnsOk()
{
//Arrange
var mockService = new Mock<IUserService>();
var user = new User()
{
UserId = 4,
IsAdmin = true,
Token = "12983912803981",
IsLogged = true,
MessagesSent = null,
MessagesReceived = null,
Nickname = "test3",
Password = "Str0ngP@ssword123",
UserChannels = null
};
var controller = new UsersController(_repository, _logger, mockService.Object);
//Act
var result = controller.Authenticate(user);
//Assert
var okResult = result.Should().BeOfType<OkObjectResult>();
}
但是,单元测试返回BadRequest,而不是预期的OkObjectResult。 这可能意味着该用户实际上为空,并且抛出了BadRequest。我应该模拟存储库而不是IUserService吗?
答案 0 :(得分:4)
实际上,您相当不错,并且可以完美地完成所有工作(很少有开发人员实际使用AAA,这非常可悲),但请记住,默认情况下,Mock返回的是 default(T)值。因此,将对您的Authenticate方法进行模拟并返回默认(用户),该值为空。 只需使其返回您的存根用户即可:
var mockService = new Mock<IUserService>();
var user = new User()
{
UserId = 4,
IsAdmin = true,
Token = "12983912803981",
IsLogged = true,
MessagesSent = null,
MessagesReceived = null,
Nickname = "test3",
Password = "Str0ngP@ssword123",
UserChannels = null
};
mockService.Setup(x=> x.Authenticate(It.IsAny(), It.IsAny())).Returns(user);
或更多由@ xander 提出的 strict 版本:
mockService.Setup(x=> x.Authenticate("test3", "Str0ngP@ssword123")).Returns(user);
它还将检查您是否确实使用了传入的User中的值,而不仅仅是盲目地返回Ok()。