Unit Testing Controllers in ASP.NET Web API
WebAPI
19 Articles
In this article, let's learn about how to unit test Controllers
in WebAPI
in ASP.NET Core.
Table of Contents
- Introduction
- Why Unit Testing?
- What is a Controller?
- Unit Testing Controller
- Verifying Action Result
- Verifying Model Type
- Verifying Model Content
- Combining All Together
- Summary
Introduction
In this article, we will focus on unit testing thick controllers
, which are controllers that contain behavior suitable for
testing. While it's ideal to start with thin controllers, it's not always possible, especially when working with existing projects or teams that have different
design decisions. Writing pragmatic unit tests for thick controllers can greatly improve the application's reliability.
Why Unit Testing ?
Unit testing
allows developers to verify the behavior and logic of individual units of code in isolation
.
By writing tests, you can ensure that your code functions correctly and remains reliable even after making changes or adding new features. Unit tests help catch
bugs early in the development process and provide confidence in the correctness of the code.
Note: If you have not done so already, I recommend you read the article on Implementing TDD in C# .Net.
What is a Controller ?
When it comes to testing API controllers
in ASP.NET Core, it's important to consider the behavior contained
within the controllers. Controllers can be categorized as thick
or thin
. Thick controllers
contain logic and behavior that can be tested, such as model state checks, database calls, mapping code, and conditional code
.
On the other hand, thin controllers delegate the implementation of behavior to other components and typically don't require unit testing
.
Unit Testing Controller
To test API controllers in ASP.NET Core, it's crucial to isolate the controller's behavior from external dependencies, such as model binding,
filters, and routing
. Unit testing should focus on testing the controller's behavior itself, avoiding testing the ASP.NET Core framework.
Veriyfing Action Result
One aspect of testing API controllers is verifying the type of ActionResult
returned from a specific action. In many cases,
ActionResult<T>
is used as the return
type, allowing for flexibility in returning
different types of action results
. To test the ActionResult
type, you can
assert
that the returned result
is of the expected type, such as
OkObjectResult
, NotFoundObjectResult
, or BadRequestObjectResult
.
Here's an example of testing the type of ActionResult returned from the GetBlogs
action:
Code Sample - WebAPI Controller Action Result Test
Veriyfing Model Type
Another important aspect of testing API controllers is verifying the expected model type
returned by the action. The model
type is the generic type
parameter of the ActionResult<T>
. You can use the
Assert.IsAssignableFrom
method to check if the returned model is assignable to the expected type.
For example, let's verify that the returned model from the GetBlogs
action is of type
IEnumerable<BlogDto>
:
Code Sample - WebAPI Controller Model Type Test
Veriyfing Model Content
Finally, we're going to verify whether the returned DTO
, in our case an IEnumerable<BlogDto>
,
is correctly constructed by the action. We expect it to contain as many objects as were inputted, and in our case, we input three blogs. So what we want to test is
that we end up with three blog DTOs.
GetBlogs_GetActionMustReturnNumberOfInputtedBlogs
. There is, again, nothing to arrange. To act, we
execute the GetBlogs
method again. And to assert, we first need to get a hold of the action result. We know how to do that by
now, as it's the same as what we did in the two previous demos. Once we've got that action result, we can cast the result of the action result to an
OkObjectResult
and get the Value
property. Once we have that value, we can cast it to an
IEnumerable<BlogDto>
and count
it.
Code Sample - WebAPI Controller Model Content Test
Combining All Together
So far we focused on testing individual aspects of the controller's behavior. However, it is often useful to combine multiple asserts related to the same action in one unit test. This not only makes the test code more concise but also provides a clearer overview of the expected behavior.
To combine the asserts and fix the null
reference issues, we can make use of the ActionResult<T>
type's pattern matching capabilities. This allows us to simplify the code and handle null
values more effectively.
Let's update our test to incorporate these improvements:
Code Sample - WebAPI Controller Complete Test
Summary
In this article, we explored the process of unit testing controllers
in ASP.NET Core. We discussed the importance of unit
testing and when it is suitable to test API controllers. We focused on testing the behavior of the controllers
and provided
examples of verifying ActionResult types, model types, and model content
using C#.
Unit testing controllers allows us to ensure that the expected behavior is correctly implemented and provides valuable feedback on the reliability of our application. By isolating the tests and using mocks or framework techniques, we can focus solely on testing our code.