Spring Boot MockMVC Example

Learn to use Spring MockMVC to perform integration testing of REST controllers. The MockMVC class is part of the Spring test framework and helps in testing the controllers by explicitly starting a Servlet container.

In this MockMVC tutorial, we will use it along with Spring boot’s WebMvcTest class to execute Junit testcases that tests REST controller methods written for Spring boot 2 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. Test Configuration

A JUnit test class to test the Spring MVC controller request and responses can use the below-given configuration.

@RunWith(SpringRunner.class)
@WebMvcTest(EmployeeRESTController.class)
public class TestEmployeeRESTController {
 
  @Autowired
  private MockMvc mvc;
 
}
  • SpringRunner is an alias for the SpringJUnit4ClassRunner. It is a custom extension of JUnit’s BlockJUnit4ClassRunner which provides the functionality of the Spring TestContext Framework to standard JUnit tests by means of the TestContextManager and associated support classes and annotations.
  • 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-configure MockMvc instance as well.
  • Using EmployeeRESTController.class as parameter, we are asking to initialize only one web controller, and you need to provide the remaining dependencies required using Mock objects.

3. Using MockMVC

Let’s create some JUnit tests which 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.

Spring Boot MockMvc Example
Test Results

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 !!

Leave a Reply

10 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial