Vickarius
Vickarius

Reputation: 37

How to test a function that return Ok(new { token = tokenStr });

This is my function of a controller class, I want to test this but I didn't have any idea to know why checking the OkObject is null. I need some advice and a way to solve this:

[HttpGet]
        public async Task<IActionResult> LoginAsync(string phoneNumber, string pass)
        {
            User login = new User();
            login.Phone = phoneNumber;
            login.Password = pass;
            IActionResult response = Unauthorized();

            var user = await _loginService.AuthenticateUserAsync(login);
            if(user != null)
            {
                var tokenStr = _loginService.GenerateJWT(user);
                response = Ok(new { token = tokenStr });
            }
            return response;
        }

My test function is :

[Fact]
        public async Task LoginAsync_ReturnOk()
        {
            var mock = new Mock<ILoginService>();

            var controller = new LoginController(mock.Object);

            var phone = "0123456789";
            var pass = "abc123";
            var okResult = await controller.LoginAsync(phone, pass);
            Assert.IsType<OkObjectResult>(okResult as OkObjectResult);


        }

I really need help from you.

Upvotes: 2

Views: 1106

Answers (1)

Nkosi
Nkosi

Reputation: 247333

The test is failing because the mocked dependency has not been configured to behave as expected for the current test case.

The subject under test for the stated test case needs

//...

 if(user != null)

//...

to be true but the _loginService was not configured for the test case

//...

var user = await _loginService.AuthenticateUserAsync(login);

//...

That means that the subject under test will return UnauthorizedResult

This will cause okResult as OkObjectResult to be null

The test needs to be arranged so that the test case, when exercised, will behave as expected

[Fact]
public async Task LoginAsync_Should_Return_Ok() {
    // Arrange
    var mock = new Mock<ILoginService>();

    var user = new UserResult(); //Or what ever the actual user type is
    
    mock.Setup(_ => _.AuthenticateUserAsync(It.IsAny<User>()))
        .ReturnsAsync(user);

    string tokenStr = "some token value";

    mock.Setup(_ => _.GenerateJWT(user)).Returns(tokenStr);

    LoginController controller = new LoginController(mock.Object);

    string phone = "0123456789";
    string pass = "abc123";

    //Act
    IActionResult response = await controller.LoginAsync(phone, pass);

    //Assert
    OkObjectResult okResult = Assert.IsType<OkObjectResult>(response);
    
    //Optional: additional assertions for this test case
    dynamic value = okResult.Value;
    Assert.NotNull(value);

    string token = (string)value.token;
    Assert.Equal(token, tokenStr);
}

And since there is also the possible outcome of having an unauthorized response, here is the other test case to cover that controller action

[Fact]
public async Task LoginAsync_Should_Return_Unauthorized() {
    //Arrange
    var mock = new Mock<ILoginService>();
    mock.Setup(_ => _.AuthenticateUserAsync(It.IsAny<User>()))
        .ReturnsAsync((UserResult)null); //Or what ever the actual user type is

    LoginController controller = new LoginController(mock.Object);

    string phone = "0123456789";
    string pass = "abc123";

    //Act
    IActionResult response = await controller.LoginAsync(phone, pass);

    //Assert
    Assert.IsType<UnauthorizedResult>(response);
}

Upvotes: 2

Related Questions