I\'m in the process of building an ASP.NET Core WebAPI and I\'m attempting to write unit tests for the controllers. Most examples I\'ve found are from the older WebAPI/WebA
Other answers adviced to cast to ObjectResult
, but its work only if you return OkObjectResult
\ NotFoundObjectResult
\ etc. But server could return NotFound
\ OkResult
which derived from StatusCodeResult
.
For example:
public class SampleController : ControllerBase
{
public async Task<IActionResult> FooAsync(int? id)
{
if (id == 0)
{
// returned "NotFoundResult" base type "StatusCodeResult"
return NotFound();
}
if (id == 1)
{
// returned "StatusCodeResult" base type "StatusCodeResult"
return StatusCode(StatusCodes.Status415UnsupportedMediaType);
}
// returned "OkObjectResult" base type "ObjectResult"
return new OkObjectResult("some message");
}
}
I looked at the implementation of all these methods and found that they are all inherited from the IStatusCodeActionResult
interface. It seems like this is the most base type that contains StatusCode
:
private SampleController _sampleController = new SampleController();
[Theory]
[InlineData(0, StatusCodes.Status404NotFound)]
[InlineData(1, StatusCodes.Status415UnsupportedMediaType)]
[InlineData(2, StatusCodes.Status200OK)]
public async Task Foo_ResponseTest(int id, int expectedCode)
{
var actionResult = await _sampleController.FooAsync(id);
var statusCodeResult = (IStatusCodeActionResult)actionResult;
Assert.Equal(expectedCode, statusCodeResult.StatusCode);
}
You can also do cool things like:
var result = await controller.GetOrders();//
var okResult = result as ObjectResult;
// assert
Assert.NotNull(okResult);
Assert.True(okResult is OkObjectResult);
Assert.IsType<TheTypeYouAreExpecting>(okResult.Value);
Assert.Equal(StatusCodes.Status200OK, okResult.StatusCode);
Thanks
Assuming something like the
public IActionResult GetOrders() {
var orders = repository.All();
return Ok(orders);
}
the controller in this case is returning an OkObjectResult class.
Cast the result to the type of what you are returning in the method and perform your assert on that
[Fact]
public void GetOrders_WithOrdersInRepo_ReturnsOk() {
// arrange
var controller = new OrdersController(new MockRepository());
// act
var result = controller.GetOrders();
var okResult = result as OkObjectResult;
// assert
Assert.IsNotNull(okResult);
Assert.AreEqual(200, okResult.StatusCode);
}
You also can use ActionResult class as a controller result (assuming you have type Orders). In that case you can use something like this:
[ProducesResponseType(typeof(Orders), StatusCodes.Status200OK)]
public ActionResult<Orders> GetOrders()
{
return service.GetOrders();
}
and now in unit tests you have:
Assert.IsInstanceOf<Orders>(result.Value);
Besides, this is the recommendation of Microsoft - https://docs.microsoft.com/en-us/aspnet/core/web-api/action-return-types?view=aspnetcore-2.2#actionresultt-type
Unfortunately, I don't know why using Ok method
return Ok(service.GetOrders());
doesn't map it properly.