Unit tests are used to test the smaller units of an application. Unit tests make sure that a unit of code is working as expected. There are many unit testing frameworks available in Java. Example: TestNG, JUnit, Mockito, etc. With these frameworks, we can easily add spring boot controller JUnit test cases.
In this article, we will learn how to write JUnit test cases for Spring boot REST APIs. We will use JUnit 5 and Mockito to write the unit test cases.
Technologies used in this article are:
- Spring Boot version : 2.3.1.BUILD-SNAPSHOT
- Java version 1.8
- JUnit 5
Table of Contents
- Create a Spring boot application
- Create REST endpoints
- Writing the RestController Unit Tests
- Run the Unit tests
- Conclusion
Create a Spring boot application
Create a Spring Boot application with required dependency. We need spring-boot-starter-web dependency for supporting REST API creation and spring-boot-starter-test dependency for adding test framework libraries to the application.
Since we are writing JUnit 5 test cases, junit-vintage-engine has been excluded(used for running JUnit 4 test cases).
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency>
Create REST endpoints
We will create simple CRUD endpoints for the Student DTO class. We will create a RestController class, a service class, and a DTO class.
Student DTO class
Let us create a DTO class with the name Student.java
package com.asbnotebook.dto; public class Student { private Integer id; private String name; //getters and setters }
RestController class
Create a RestController class with the name StudentController.java
This class will have CRUD REST endpoints for Student DTO.
The class uses the StudentService service class to perform the CRUD operation.
package com.asbnotebook.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.asbnotebook.dto.Student; import com.asbnotebook.service.StudentService; @RestController public class StudentController { @Autowired private StudentService studentService; @GetMapping("/getMapping") public ResponseEntity<List<Student>> getStudents() { List<Student> students = studentService.getStudents(); return new ResponseEntity<>(students, HttpStatus.OK); } @PostMapping("/postMapping") public ResponseEntity<Student> saveStudent(@RequestBody Student student) { student = studentService.saveStudent(student); return new ResponseEntity<>(student, HttpStatus.CREATED); } @PutMapping("/putMapping") public ResponseEntity<Student> putExample(@RequestBody Student student) { student = studentService.updateStudent(student); return new ResponseEntity<>(student, HttpStatus.OK); } @DeleteMapping("/deleteMapping") public ResponseEntity<String> deleteExample(@RequestParam("student-id") String studentId) { String response = studentService.deleteStudent(studentId); return new ResponseEntity<>(response, HttpStatus.OK); } }
Student Service class
Create a StudentService.java service class. This class provides the required functionalities to the controller layer.
package com.asbnotebook.service; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Service; import com.asbnotebook.dto.Student; @Service public class StudentService { public List<Student> getStudents() { List<Student> students = new ArrayList<>(); Student student = new Student(); students.add(student); return students; } public Student saveStudent(Student student) { student.setId(1); student.setName("Arun"); return student; } public Student updateStudent(Student student) { student.setId(2); student.setName("John"); return student; } public String deleteStudent(String studentId) { return "Student is deleted"; } }
Writing the RestController Unit Tests
Create a JUnit test class with the name StudentControllerTest.java under the /src/test directory. Add the code given below.
package com.asbnotebook; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.util.ArrayList; import java.util.List; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.mockito.ArgumentMatchers; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import com.asbnotebook.dto.Student; import com.asbnotebook.service.StudentService; import com.fasterxml.jackson.databind.ObjectMapper; @WebMvcTest public class StudentControllerTest { @Autowired private MockMvc mockMvc; @MockBean private StudentService studentService; private static ObjectMapper mapper = new ObjectMapper(); @Test public void testGetExample() throws Exception { List<Student> students = new ArrayList<>(); Student student = new Student(); student.setId(1); student.setName("Arun"); students.add(student); Mockito.when(studentService.getStudents()).thenReturn(students); mockMvc.perform(get("/getMapping")).andExpect(status().isOk()).andExpect(jsonPath("$", Matchers.hasSize(1))) .andExpect(jsonPath("$[0].name", Matchers.equalTo("Arun"))); } @Test public void testPostExample() throws Exception { Student student = new Student(); student.setId(1); student.setName("Arun"); Mockito.when(studentService.saveStudent(ArgumentMatchers.any())).thenReturn(student); String json = mapper.writeValueAsString(student); mockMvc.perform(post("/postMapping").contentType(MediaType.APPLICATION_JSON).characterEncoding("utf-8") .content(json).accept(MediaType.APPLICATION_JSON)).andExpect(status().isCreated()) .andExpect(jsonPath("$.id", Matchers.equalTo(1))) .andExpect(jsonPath("$.name", Matchers.equalTo("Arun"))); } @Test public void testPutExample() throws Exception { Student student = new Student(); student.setId(2); student.setName("John"); Mockito.when(studentService.updateStudent(ArgumentMatchers.any())).thenReturn(student); String json = mapper.writeValueAsString(student); mockMvc.perform(put("/putMapping").contentType(MediaType.APPLICATION_JSON).characterEncoding("utf-8") .content(json).accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk()) .andExpect(jsonPath("$.id", Matchers.equalTo(2))) .andExpect(jsonPath("$.name", Matchers.equalTo("John"))); } @Test public void testDeleteExample() throws Exception { Mockito.when(studentService.deleteStudent(ArgumentMatchers.anyString())).thenReturn("Student is deleted"); MvcResult requestResult = mockMvc.perform(delete("/deleteMapping").param("student-id", "1")) .andExpect(status().isOk()).andExpect(status().isOk()).andReturn(); String result = requestResult.getResponse().getContentAsString(); assertEquals(result, "Student is deleted"); } }
Few of the points to notice here are:
- @WebMvcTest: This annotation initializes web MVC related configurations required to write the JUnit test case for controller classes.
- MockMvc: This class provides the required methods to test the Spring MVC layer. with perform() method, we can test different HTTP endpoints(GET, POST, PUT, DELETE, etc)
- @MockBean: This annotation creates mocked beans in the spring application context.
- @Test: Indicated that the method is a test case.
- Mockito: This class of Mockito framework creates a mock of an object. We have mocked the return values of the service layer in our example.
- jsonpath: Spring boot provides built-in supports JsonPath that is helpful to verify the JSON response.
- MvcResult: MockMvc returns a result object on calling andReturn(), that contains the response details of a particular MVC operation.
Run the Unit tests
Now we can run our JUnit test cases. With IDE like STS/Eclipse, we can run the test case by Right click on Project > Run AS > JUnit.
If every test case runs successfully, we get JUnit output similar to the below image.

Conclusion
In this article, we learned how to write Unit test cases for Spring boot REST APIs using the JUnit 5 and Mockito.
The complete example code is available on Github. Happy coding 🙂