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.