简体   繁体   中英

How to test my ASP.NET Core 2.2 Web API GET IActionResult that returns Ok(object)?

In my Web API I have a simple controller action:

[HttpGet]
[Route("[action]")]
public IActionResult GetApiStatus(string token)
{
    if (_token != token)
    {
        return StatusCode(401);
    }

    StatusModel status = _vesselUpdating.GetUpdatingStatus();

    return Ok(status);
}

And action returns StatusModel type object. I could not manage how to test its return status.

My test method is below:

[Theory]
[InlineData("wrong_token", StatusCodes.Status401Unauthorized)]
[InlineData("test_token", StatusCodes.Status200OK)]
[InlineData("", StatusCodes.Status401Unauthorized)]
[InlineData(null, StatusCodes.Status401Unauthorized)]
public void Get_GetAnyAction_WithVariusTokens_ReturnsCorrectStatusCode(string token, int code)
{
    _vesselUpdatingMock.Setup(v => v.GetUpdatingStatus()).Returns(_sampleStatusModel);
    IActionResult result;

    result = _updatesController.GetApiStatus(token);
    StatusCodeResult resultGetApiStatus = result as StatusCodeResult;

    Assert.Equal(code, resultGetApiStatus.StatusCode);
}

When debugging on

result = _updatesController.GetApiStatus(token);

the StatusCode property of IActionResult is 200 , but only DeclaredType property of that is null .

结果调试

And when Asserting, at the end I have in my resultGetApiStatus null .

断言空

I did not managed to find similar example. How can I project result properly?

IMPORTANT EDIT:

I found only this approach , that does not fix my problem, regarding variety of cases [Theory] , and not all my other actions returns ObjectResult , some of them return only StatusCode . Is there any universal approach for actions with and without ObjectResult ? Or should I use different tests?

A frustration not only you possess.

OkObjectResult does not inherit from StatusCodeResult , ergo

StatusCodeResult resultGetApiStatus = result as StatusCodeResult;

Is rightly returning null.

See: https://github.com/aspnet/Mvc/issues/7134

You should be able to coerce to an IStatusCodeActionResult

https://github.com/dotnet/aspnetcore/blob/a410ed460140a55dd699e83d978b798de48802fb/src/Mvc/Mvc.Core/src/StatusCodeResult.cs#L32 however, I'm unsure which version this shipped with (2.1?)

[Theory]
[InlineData("wrong_token", StatusCodes.Status401Unauthorized)]
[InlineData("test_token", StatusCodes.Status200OK)]
[InlineData("", StatusCodes.Status401Unauthorized)]
[InlineData(null, StatusCodes.Status401Unauthorized)]
public void Get_GetAnyAction_WithVariusTokens_ReturnsCorrectStatusCode(string token, int code)
{
    _vesselUpdatingMock.Setup(v => v.GetUpdatingStatus()).Returns(_sampleStatusModel);

    var result = _updatesController.GetApiStatus(token);
    var resultGetApiStatus = result as IStatusCodeActionResult;

    Assert.Equal(code, resultGetApiStatus.StatusCode);
}

The testing logic is flawed, which also leads to mixed outcomes based on the provided inputs applied to the subject under test.

Test for specific outcomes based on the expected behavior that allow for one logical path to be tested in the subject.

For example

[Theory]
[InlineData("wrong_token")]
[InlineData("")]
[InlineData(null)]
public void Get_GetAnyAction_WithInvalidTokens_ReturnsUnauthorizedStatusCode(string token) {
    //Arrange
    int expected = StatusCodes.Status401Unauthorized;

    //Act
    StatusCodeResult result = _updatesController.GetApiStatus(token) as StatusCodeResult;

    //Assert
    int actual = result.StatusCode;
    Assert.Equal(expected, actual);
}

[Fact]
public void Get_GetAnyAction_WithValidToken_ReturnsCorrectStatusCode() {
    //Arrange
    _vesselUpdatingMock.Setup(v => v.GetUpdatingStatus()).Returns(_sampleStatusModel);
    string token = "test_token";

    //Act
    OkObjectResult result = _updatesController.GetApiStatus(token) as OkObjectResult;

    //Assert
    int expected = StatusCodes.Status200OK;
    int actual = result.StatusCode;
    Assert.Equal(expected, actual);
}

That way you avoid having to add conditional logic to the test which would mean the test is doing too much

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM