In this article, we will learn how to create a JUnit 5 test classes with Mockito in Spring Boot application. JUnit is one of the most popular testing frameworks for Java applications. JUnit 5 supports all modern features from Java 8 and allows using many different approaches and styles in testing.
2. Maven dependencies
Fortunately, the spring-boot-starter-test dependency from version 2.2.0 already comes with Junit 5 and contains also Hamcrest, and Mockito libraries for testing. That's good news because we don't need to add a lot of dependecy into our final pom.xml file.
The JUnit 5 is composed of three sub-projects, such as:
JUnit Platform - for launching testing frameworks on the JVM,
JUnit Jupiter - for writing tests and extensions in JUnit 5,
JUnit Vintage - provides a TestEngine for running JUnit 3 and JUnit 4 based tests on the platform.
For our case, we don't need JUnit 3 and JUnit 4 support that's why we will exclude this dependency.
The final pom.xml has the following structure:
We have two main dependecies:
spring-boot-starter-web - web container is used for creating Spring REST API,
spring-boot-starter-test - main dependencies for unit and intergration testing.
The spring-boot-maven-plugin is used to create an executable jar with the Spring Boot application.
3. Project structure
The testing project has the following structure:
Here we could distinguish the following classes:
Application - the main Spring Boot application class used for starting web container,
HelloController - Spring Rest Controller for testing purposes,
HelloService - Spring Service used to check how autowire works in tests,
HelloControllerMockitoTest - test for HelloController using Mockito,
HelloControllerMockMvcTest - test for HelloController using MockMvc,
HelloControllerRestTemplTest - test for HelloController using TestRestTemplate.
4. Spring REST API for JUnit 5 Testing
Spring REST controller called HelloController will be used as our main class for testing. It uses @Autowired annotation to inject HelloService.
The HelloController has the following structure:
@GetMapping annotation marks greeting() method that from now will be used to handle all GET requests to the root path /.
5. Hello Service
The HelloService is a simple Spring service with method getWelcomeMessage() that will be run in REST controller class:
Main Spring Boot application class is marked with @SpringBootApplication annotation and contains a single public static void main(String args) method that starts web container - Tomcat by default.
7. Test using MockMvc to perform REST calls
Let's start our testing adventure with a test class that uses MockMvc. In this approach, the Spring Boot application server will not be started but the code will be called exactly in the same way as if it handling an HTTP request.
The test class looks as follows:
We used the MockMvc class and @AutoConfigureMockMvc that will configure it and inject it into the tested class. The MockMvc class is used to perform API calls, but instead of doing HTTP requests, Spring will test only the implementation that handle them in HelloController.
8. Spring boot test that makes use of TestRestTemplate to call REST API
In the next approach, we will use the @SpringBootTest annotation that is used to start the Spring application context.
In this approach, we can use @Autowired annotation just like in runtime applications. Spring will interpret them and do the necessary injections. In @SpringBootTest tests real Spring Boot application server is being started.
In the test we used:
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT - to start the server with a random port in order to avoid any port conflicts,
@LocalServerPort - this annotation tells Spring to inject a random port to the specific field,
TestRestTemplate - RestTemplate for tests used to make a real HTTP requests.
9. Mockito unit test for HelloController class
In case we want to mock some objects while testing the HelloController class we could use the Mockito framework in a unit test. In this approach, we are simply testing class with JUnit and Mockito without making any HTTP calls. It is possible because our REST controller is an ordinary class like any other.
To start using Mockito in JUnit tests we need to annotate a class with @ExtendWith(MockitoExtension.class). In our testing class, we mock HelloService to change the response of getWelcomeMessage() method. The @InjectMocks annotation tells Mockito to inject all mock objects into the test class.
In this article, we presented several approaches to test the Spring REST controller using JUnit 5 and the Mockito library. It is up to us if we want to start the real Spring Boot server using @SpringBootTest annotation or simply run the implementation that is called on HTTP requests using MockMvc. Mockito could be also used to test the REST controller class if there is a need to mock or spy dependencies.
As usual, code used in this tutorial is available on our GitHub.