Nunit async test exception assertion
You're seeing problems due to async void
.
In particular:
async () => await userController.Get("foo")
is converted intoTestDelegate
, which returnsvoid
, so your lambda expression is treated asasync void
. So the test runner will begin executing the lambda but not wait for it to complete. The lambda returns beforeGet
completes (because it'sasync
), and the test runner sees that it returned without an exception.Wait
wraps any exceptions in anAggregateException
.Again, the
async
lambda is being treated asasync void
, so the test runner is not waiting for its completion.I recommend you make this
async Task
rather thanasync void
, but in this case the test runner does wait for completion, and thus sees the exception.
According to this bug report, there is a fix for this coming in the next build of NUnit. In the meantime, you can build your own ThrowsAsync
method; an example for xUnit is here.
I'm not sure when it was added, but the current version of Nunit (3.4.1 at time of writing) includes a ThrowsAsync method
see https://github.com/nunit/docs/wiki/Assert.ThrowsAsync
Example:
[Test]
public void ShouldThrow404WhenNotFound()
{
var mockUserRepository = new Mock<IUserRepository>();
mockUserRepository.Setup(x => x.GetByUserName(It.IsAny<string>())).Returns(default(User));
var userController = new UserController(mockUserRepository.Object) { Request = new HttpRequestMessage() };
var exception = Assert.ThrowsAsync<HttpResponseException>(() => userController.Get("foo"));
Assert.That(exception.Response.StatusCode, Is.EqualTo(HttpStatusCode.NotFound));
}