Looking for guidance on unit testing controllers in asp.net web api 2. I have a standard multi-tier architecture: controllers -> servicelayer -> data access layer.
The service layer may throw exceptions originating from the service layer or exceptions from the data access layer [1]. Since the exception handling logic in each controller's method is pretty cookie cutter:
public IHttpActionResult MyControllerAction()
{
try
{
// do something and return IHttpActionResult
}
catch(Exception ex)
{
// map exceptions to specific IHttpActionResult with corresponding (status code and error (response body) formatting)
return HandleException(ex);
}
}
I opted to lift the try/catch & handling logic out of each of controller action and consolidate it in one place. One of the following would work: {IHttpActionInvoker, ExceptionFilter, or ExceptionHandler}.
Unfortunately, because the exception handling logic is now out of the controller my controller unit tests are no longer isolated at the IHttpActionResult level.
Previously I could test various inputs and expected outputs like:
- Given: input1, Expect IHttpActionResult: OK
- Given: input2, Expect IHttpActionResult: NotFound
- Given: input3, Expect IHttpActionResult: BadRequest
- Given: input4, Expect IHttpActionResult: PreconditionFailed
- ...
This felt very clean conceptually, my controllers and unit tests all interact with well known IHttpActionResults (not service layer or lower concepts).
Now that I lifted the exception handling out to a global handler, the controller unit tests now throw a myriad of service or data access layer exceptions. Of course, I could achieve what I had previously with an integration test, e.g. ExceptionHandler + controller.
Question: In such a setup, what is the value in unit testing the controllers in isolation? Seems like a baseline value would be to have an integration test with ExceptionHandler + controller to at least validate all the status code's returned from various inputs.
[1] data acccess exceptions are generic and agnostic to a particular data access implementation. I didn't see a value to wrap it in a service layer exception.