Unit testing your API Controllers — A code walkthrough
In the previous blog, we talked about why you should be testing your API controllers with the common pitfalls that come along with it. Now, theory without a code walkthrough is like fool’s gold. Beautiful to look at, but of no relevance. (Nerd fact : The element Pyrite is commonly known as Fool’s gold)
So we ended that blog mentioning that we would follow up with a code walkthrough and voila! Here we are! Let’s get to the meat of the matter then.
For the purpose of this blog, we have created a basic spring-boot based project. It’s an employee management system (a bare extraction of the supposed mammoth project). A DAO to store the employees in the organisation. A client interacts with the DAO to check the details of the employee add CRUD operations for the same.
Let’s start with the employee DAO and the employee POJO.
Then we add a service implementation to fetch the employee details. Here, we have stubbed the db connection logic and hard-coding an employee for test purpose.
Finally, we add a controller to fetch the employee details via API :
So we have an API which returns the employee details if the employee exists, otherwise throws an exception. Let’s see how we can test the same by using @webMvcTest annotation provided by spring.
Let’s add a test file to test our controller. We will name this class as EmployeeControllerTests.
Here we set jUnit’s default runner to run the tests with @RunWith annotation provided by spring. Next, @webMvcTest annotation tells the class to disable full auto-configuration and instead apply only configuration relevant to MVC tests.
Now we are all set to add tests. Let’s add our first happy test case.
In above test, we first create a dummy employee object to stub out the service layer call. We are just bothered about the controllers. Next, with mockMvc, we perform an API call and assert the response. Here, we are asserting the status code and the response body itself. On the similar lines, you can add assertions for headers, content-type, errors, forward URLs, redirect URLs. This really opens up new dimensions for testing the logic in controllers with just enabling a slice of the entire project.
MockMvcResultMatchers provides a plethora of APIs to test our controller response and verify for all sorts of test cases. You should check it out for more details.
Next, let’s see one more example of how we can test any exception thrown by the controller.
Here, we check that the status is NotFound and the body is empty. This would have been more meaningful if you are using custom error handling in your code with @ControllerAdvice annotation. I leave that to you as an exercise to dig deep.
So, we saw how we can bring up just a slice of your application and save a considerable amount of test sanity time. Then we saw how we can test the logic of our controllers or check the sanity of the APIs by just stubbing out the business logic.
The more you delve into it, the more use cases you would find based on your project structure. I implore you to play around with it and see how creative your tests can be.
I have run the entire code in my IDE and have also pushed the same in github. Please leave comments if you find this useful. Let us know what creative tests you are writing for your controllers.