Search code examples
.netasp.net-web-apiasp.net-corecqrsmediatr

Should I test CQRS Handlers or the whole request output in Web Api Core


I've been creating Web API for a while and was happy to be able to test CQRS Handlers (managed with Mediatr) without touching on any kind of infrastructure code (controllers, requets, etc.).And it made total sense as my controllers were extremely thin as they were doing what controllers are supposed to do: communicate between request and response:

    [HttpGet("requests")]
    public async Task<IEnumerable<AbsenceRequest>> GetAbsenceRequests(GetAbsenceRequests.Query query)
    {
        return await _mediator.Send(query);
    }

But still there were cases that my Handlers tests did not cover. Here's a couple of examples:

  1. Authorization. I could not test if a "wrong" user tried to access a specific action, he received denied access error. In other words, I could not tests authorization attributes for a specific action.
  2. Error handling. I could check that my Handler threw a specific exception under specific conditions but I could not control how infrastructure (i. e. exception middleware) handled this exception (i. e. resulted in a specific HTTP error).

ASP.NET Core made request-in response-out integration tests extremely easy (thanks to TestServer) and I can cover those two cases in my integration tests.

The question that bothers me is whether I should keep Handlers tests or test actions by sending requests and asserting the response instead.

I really love Handler tests. They're cute, clear and easy to write. Testing the whole request is much more powerful but at the same time messier as it's a relatively low-level approach and you have to deal with http and json.

I find this choice very confusing and would like to know what is the recommended approach.


Solution

  • I would test your handlers using unit tests, because these tests can run more quickly and should be less brittle than testing the handlers through MVC. There's no good reason to couple all of your tests of your handlers to your current MVC implementation. When making a decision about whether to write a unit test or an integration test, the question should be "Can I test this with a unit test?" If the answer is yes, then write a unit test.

    Now, that said, integration tests in ASP.NET Core using TestServer are awesome (I wrote the docs on them). There are things you can't test with a unit test (of your handler or of a controller action method), like whether your routes are set up correctly, or your MVC error handling, or filters, or model binding. You should write tests to confirm this behavior, using integration tests and TestServer (if you think they add value, that is). You shouldn't test all the same scenarios you already have unit tests for - that would be a waste. But you can verify different things that your unit tests couldn't by using this approach.