Learn to use Spring MockMvc to perform integration testing of REST controllers. The Spring MockMvc class is part of the Spring test framework and helps in testing the controllers by explicitly starting a Servlet container.
In this Spring Boot MockMvc tutorial, we will use MockMvc along with Spring’s @WebMvcTest annotation to execute JUnit tests for REST controller handler methods written for the Spring Boot HATEOAS example.
1. Maven
The spring-boot-starter-test
dependency includes all required dependencies to create and execute tests.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
If not using spring boot then include the following dependencies. we can also use JUnit 5 dependencies.
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>{version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>{version}</version>
<scope>test</scope>
</dependency>
2. Unit Test Structure
A JUnit test class to test the Spring MVC controller request and responses can use the below-given configuration.
@WebMvcTest(EmployeeRESTController.class)
public class TestEmployeeRESTController {
@Autowired
private MockMvc mvc;
// Your test methods would go here
// ...
}
- The
@WebMvcTest
annotation is used for Spring MVC tests. It disables full auto-configuration and instead applies only configuration relevant to MVC tests. - The
@WebMvcTest
annotation auto-configureMockMvc
instance as well. - Using
EmployeeRESTController.class
as the parameter, we are asking to initialize only one web controller, and we need to provide the remaining dependencies required usingMock
objects.
3. Spring Boot MockMvc Example
Let’s create some JUnit tests that will test different HTTP methods in the controller class.
3.1. HTTP GET API
The HTTP APIs defined in the controller are given below. In the given tests, we are testing two GET APIs – one without a path parameter and another with a path parameter.
@GetMapping(value = "/employees")
public EmployeeListVO getAllEmployees()
{
//code
}
@GetMapping(value = "/employees/{id}")
public ResponseEntity<EmployeeVO> getEmployeeById (@PathVariable("id") int id)
{
//code
}
And corresponding tests for the methods are given below. These tests hit the APIs, pass the path parameters using MockMvcRequestBuilders and verify the status response codes and response content using MockMvcResultMatchers and MockMvcResultHandlers.
@Autowired
private MockMvc mvc;
@Test
public void getAllEmployeesAPI() throws Exception
{
mvc.perform(MockMvcRequestBuilders
.get("/employees")
.accept(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.employees").exists())
.andExpect(MockMvcResultMatchers.jsonPath("$.employees[*].employeeId").isNotEmpty());
}
@Test
public void getEmployeeByIdAPI() throws Exception
{
mvc.perform( MockMvcRequestBuilders
.get("/employees/{id}", 1)
.accept(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.employeeId").value(1));
}
3.2. HTTP POST API
The HTTP POST API is defined in the controller as:
@PostMapping(value = "/employees")
public ResponseEntity<EmployeeVO> addEmployee (@Valid @RequestBody EmployeeVO employee)
{
//code
return new ResponseEntity<EmployeeVO>(employee, HttpStatus.CREATED);
}
And corresponding mockmvc test for post JSON request is as follows:
@Autowired
private MockMvc mvc;
@Test
public void createEmployeeAPI() throws Exception
{
mvc.perform( MockMvcRequestBuilders
.post("/employees")
.content(asJsonString(new EmployeeVO(null, "firstName4", "lastName4", "email4@mail.com")))
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isCreated())
.andExpect(MockMvcResultMatchers.jsonPath("$.employeeId").exists());
}
public static String asJsonString(final Object obj) {
try {
return new ObjectMapper().writeValueAsString(obj);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
3.3. HTTP PUT API
The HTTP API is defined in the controller as:
@PutMapping(value = "/employees/{id}")
public ResponseEntity<EmployeeVO> updateEmployee (@PathVariable("id") int id, @Valid @RequestBody EmployeeVO employee)
{
//code
return new ResponseEntity<EmployeeVO>(emp, HttpStatus.OK);
}
And corresponding tests for the methods are:
@Test
public void updateEmployeeAPI() throws Exception
{
mvc.perform( MockMvcRequestBuilders
.put("/employees/{id}", 2)
.content(asJsonString(new EmployeeVO(2, "firstName2", "lastName2", "email2@mail.com")))
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.firstName").value("firstName2"))
.andExpect(MockMvcResultMatchers.jsonPath("$.lastName").value("lastName2"))
.andExpect(MockMvcResultMatchers.jsonPath("$.email").value("email2@mail.com"));
}
3.4. HTTP DELETE API
The HTTP API is defined in the controller as:
@DeleteMapping(value = "/employees/{id}")
public ResponseEntity<HttpStatus> removeEmployee (@PathVariable("id") int id)
{
//code
return new ResponseEntity<HttpStatus>(HttpStatus.ACCEPTED);
}
And corresponding tests for the methods are:
@Test
public void deleteEmployeeAPI() throws Exception
{
mvc.perform( MockMvcRequestBuilders.delete("/employees/{id}", 1) )
.andExpect(status().isAccepted());
}
3.5. Test Results
When we run the above tests, we get the test results below.

4. Conclusion
In this spring boot integration test example, we learned to write Spring MVC integration tests using MockMvc class. We learned to write JUNit tests for HTTP GET, POST, PUT and DELETE APIs.
We also looked to verify API response status and response body, pass HTTP headers, and request path parameters as well.
Happy Learning !!
Comments