asp.net-mvc.net-6.0moqwebapiweb-api-testing

Write TDD test with Mock for Web API project with dot net 6.0 and Unit Of Work


I have a Web API project, I use Unit Of Work pattern with dot net 6.0 and want to write test for it.

I have a controller like below and a function in it for authentication:

public AuthController(IUnitOfWork uow, IStringLocalizer<SharedTranslate> localizer, IJwtAuthenticatorManager jwtAuthenticatorManager) : base(uow, localizer)
{
    //...
}

[HttpPost("authenticate")]
public async Task<IActionResult> Authenticate([FromBody] UserLoginViewModel Request)
{
    User user = await _uow.UserRepository.GetAsync(u => u.Username == Request.Username);
    //...
}

For a unit test with Moq, I use below code:

var unitOfWork = new Mock<IUnitOfWork>();
 unitOfWork
 .Setup(uow => 
 uow.UserRepository.GetAsync(It.IsAny<Expression<Func<User, bool>>>()))
.ReturnsAsync(new User());
var localizor = new Mock<IStringLocalizer<SharedTranslate>>();
var jwtManager = new Mock<IJwtAuthenticatorManager>();
var controller = new AuthController(unitOfWork.Object, localizor.Object, jwtManager.Object);
UserLoginViewModel userLoginViewModel = new UserLoginViewModel
{
    Username = "test",
    Password = "test"
};
var result = await controller.Authenticate(userLoginViewModel);

When I debug it, it can't connect to to database (for example the object user in the Authenticate function is empty) and check.

1.What is the problem?

2.Is this method good for test?


Solution

  • The unitOfWork.UserRepository is going to be null by default, and even if it not, Moq doesn't know what to return when the GetAsync method is called. You have to tell it:

    var unitOfWork = new Mock<IUnitOfWork>();
    unitOfWork
        .Setup(uow => uow.UserRepository.GetAsync(It.IsAny<Func<User, bool>>()))
        .ReturnsAsync(new User());
    

    This assumes that GetAsync is defined like this:

    Task<User> GetAsync(Func<User, bool> predicate);
    

    If not, adjust as required.