Как тестируют Spring MVC или REST контроллеры?

«Как тестируют Spring MVC или REST контроллеры?» — вопрос из категории Тестирование, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для тестирования контроллеров Spring используется комбинация JUnit 5, Spring Test модуля и Mockito.

1. Тестирование слоя контроллера изолированно (@WebMvcTest): Загружается только веб-слой контекста, все зависимости контроллера мокаются.

   @WebMvcTest(UserController.class) // Загружаем только контроллер и MVC инфраструктуру
   class UserControllerSliceTest {

       @Autowired
       private MockMvc mockMvc; // Главный инструмент для имитации запросов

       @MockBean
       private UserService userService; // Зависимость контроллера заменяется mock-объектом

       @Test
       void getUserById_ShouldReturnUser() throws Exception {
           // Given
           User mockUser = new User(1L, "Alice");
           when(userService.findById(1L)).thenReturn(Optional.of(mockUser));

           // When & Then
           mockMvc.perform(get("/api/users/1")
                   .accept(MediaType.APPLICATION_JSON))
                  .andExpect(status().isOk())
                  .andExpect(jsonPath("$.id").value(1L))
                  .andExpect(jsonPath("$.name").value("Alice"));
           verify(userService).findById(1L); // Проверяем вызов сервиса
       }
   }

2. Интеграционное тестирование (@SpringBootTest): Загружается полный контекст приложения. Используется TestRestTemplate или WebTestClient для реальных HTTP-вызовов.

   @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
   class UserControllerIntegrationTest {

       @Autowired
       private TestRestTemplate restTemplate;

       @Test
       void getUserById_Integration() {
           ResponseEntity<User> response = restTemplate.getForEntity("/api/users/1", User.class);
           assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
           assertThat(response.getBody().getName()).isNotNull();
       }
   }

Ключевые аннотации: @WebMvcTest (для срезов), @SpringBootTest (для интеграции), @MockBean (для моков в контексте Spring).