Home > Back-end >  Unit Testing Async Controller Method Returning Null with NUnit and Moq
Unit Testing Async Controller Method Returning Null with NUnit and Moq

Time:03-08

I have a .NET Core API Framework 6.0, I'm writing tests an Async Controller method using NUnit Framework I'm getting null value returned by the Controller Authentication method. When I make a similar call from Postman there is response. I assume my Moq is missing something but I have followed documentation and cannot figure out the issue.

//User Controller
    private readonly IUserService _userService;

    public UserController(IUserService userService)
    {
        _userService = userService;
    }

    [AllowAnonymous]
    [HttpPost("authenticate")]
    public async Task<IActionResult> Authenticate([FromBody] UserRequest userRequest)
    {
        try
        {
            var response = await _userService.Authenticate(userRequest); //Authenticate method is not being called, response is NULL here
            return Ok(new ApiResponse<UserResponse>().Success(response));
        }
        catch (Exception ex)
        {
            return betServerError(ex);
        }
    }

The Authenticate method is as below, the breakpoint on Line 1 is not being hit.

public async Task<UserResponse> Authenticate(UserRequest userRequest)
    {
        var user = _context.Users.Where(x => x.Email == userRequest.Email).FirstOrDefault(); //Breakpoint here is not being hit
        bool valid = false;

        if (user == null)
            throw new HttpException(HttpStatusCode.Unauthorized, "Username or password incorrect");

        //Other code ......
        
     return new UserResponse
        {
            Id = user.Id,
            Email = user.Email,
            Token = tokenString
        };
    }

UserTest.cs looks as follows:

Mock<IUserService> UserServiceMock = new Mock<IUserService>();

    [SetUp]
    public void Setup()
    {

    }
    [Test]
    public async Task should_Login()
    {
        //Arrange
        var user = new UserResponse
        {
            Id = 1,
            Email = "[email protected]",
            Token = "TEST_TOKEN"
        };
        UserServiceMock.Setup(x => x.Authenticate(new UserRequest { Email = "[email protected]", Password = "password" }))
            .Returns(Task.Run(() => user));
        var UserController = new UserController(UserServiceMock.Object);

        //Act
        var result = await UserController.Authenticate(new UserRequest { Email = "[email protected]", Password = "password1" }); //result here doesnot contain the response I expect, it has a null object
        
        //Assert
        Assert.IsNotNull(result);
        Assert.AreEqual(HttpStatusCode.OK, GetHttpStatusCode(result));
    }

CodePudding user response:

The UserRequest instance you're passing into Authenticate is a different instance than what you're setting up your mock to expect. So, since the inputs don't match, the mock is not executed, and the default mock behavior takes over.

Either remove the mock conditional (i.e., use It.IsAny<UserRequest>()), or pass the same instance to your mock and your controller method.

  • Related