Just like the repository and service layers, the controller layer can be tested too. Testing a controller means mocking the service layer (since the controller talks to the service, the same way the service talks to the repository).
Controller testing itself is done with Spring MVC, via @WebMvcTest.
Hamcrest is a well-known assertion framework, bundled with JUnit, that uses existing
predicates (“matcher” classes) to build assertions — instead of JUnit’s many assert* methods,
you use one assertThat with the appropriate matcher.
is()— verify an expected value/object equals the actual one:assertThat(ACTUAL, is(EXPECTED))
JsonPath is a Java DSL for reading JSON documents, the same way XPath is used with XML. The
root member object in JsonPath is always $, whether it’s an object or an array.
@WebMvcTest
Spring Boot’s @WebMvcTest tests Spring MVC controllers. It only loads the web layer (the
specified controller and its dependencies) rather than the whole application context, so tests
run faster. In a multi-controller app, you can scope it to one controller —
@WebMvcTest(HomeController.class). (For full integration testing, use @SpringBootTest
instead.)
@WebMvcTestclass EmployeeControllerTests {
@Autowired private MockMvc mockMvc;
@MockBean private EmployeeService employeeService;
@Autowired private ObjectMapper objectMapper;
@Test void givenEmployeeObject_whenCreateEmployee_thenReturnSavedEmployee() throws Exception { Employee employee = Employee.builder() .firstName("travis") .lastName("scott") .email("travis@gmail.com") .build();
given(employeeService.saveEmployee(any(Employee.class))) .willAnswer((invocation) -> invocation.getArgument(0));
ResultActions response = mockMvc.perform(post("/api/employees") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(employee)));
response.andExpect(status().isCreated()) .andExpect(jsonPath("$.firstName", is(employee.getFirstName()))) .andExpect(jsonPath("$.lastName", is(employee.getLastName()))) .andExpect(jsonPath("$.email", is(employee.getEmail()))); }
@DisplayName("Get All Employees Controller") @Test void givenListOfEmployees_whenGetAllEmployees_thenReturnAllEmployees() throws Exception { List<Employee> listOfEmployees = new ArrayList<>(); listOfEmployees.add(Employee.builder().firstName("ernest").lastName("sarfo").email("sarfo@gmail.com").build()); listOfEmployees.add(Employee.builder().firstName("tony").lastName("stark").email("tonystark@gmail.com").build()); given(employeeService.getAllEmployees()).willReturn(listOfEmployees);
ResultActions response = mockMvc.perform(get("/api/employees"));
response.andExpect(status().isOk()) .andExpect(jsonPath("$.size()", is(listOfEmployees.size()))); }}