JavaRush /Курсы /Модуль 5. Spring /Краткое содержание предыдущих лекций

Краткое содержание предыдущих лекций

Модуль 5. Spring
14 уровень , 3 лекция
Открыта

Вот мы и добрались до тестирования контроллеров. Контроллеры, как вы знаете, отвечают за обработку HTTP-запросов и передачу данных между клиентом и бизнес-логикой приложения. Все хотят, чтобы их контроллеры работали безупречно, но кто-то должен это проверить. Спойлер: этим кем-то будете вы. Благо, у нас есть мощный инструмент — MockMvc.

Зачем тестировать контроллеры? Ну, во-первых, тестирование контроллеров позволяет быть уверенным, что ваши эндпоинты работают (и не только в вашем браузере).

Во-вторых, контроллеры часто являются первым элементом приложения, на который падает весь гнев пользователей в случае ошибок. Например, что сделает пользователь, если запрос по URI /api/users возвращает 500 Internal Server Error? Конечно, обвинит ваш код (и, возможно, вас лично). Так что, если ваш код работает, вы защищены.


Что такое MockMvc?

MockMvc — это инструмент, предоставляемый Spring Test, который позволяет тестировать поведение веб-приложений без необходимости развертывания реального сервера. Он имитирует обработку HTTP-запросов и позволяет проверять ответы, заголовки, статусы и даже ошибки.

MockMvc позволяет отправлять тестовые HTTP-запросы к вашим контроллерам и проверять, как они на них отвечают. Например, вы можете отправить GET-запрос на /api/users и проверить, что статус ответа — 200, а тело содержит ожидаемые данные.

Вот небольшой пример взаимодействия с MockMvc:


mockMvc.perform(get("/api/users"))
    .andExpect(status().isOk())
    .andExpect(content().json("[{\"id\":1,\"name\":\"John Doe\"}]"));

Подготовка к тестированию

Прежде чем начать писать тесты, давайте убедимся, что у нас есть всё необходимое:

  1. Контроллер: напишем пример контроллера, который будем тестировать.
  2. Зависимости: добавим Spring Boot Test, JUnit и Mockito для работы.
  3. Конфигурация MockMvc: настроим MockMvc для тестов.

Шаг 1: Пример контроллера для тестирования

Предположим, у нас есть контроллер для работы с пользователями:


@RestController
@RequestMapping("/api/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping
    public List<User> getAllUsers() {
        return userService.findAll();
    }

    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user) {
        User createdUser = userService.save(user);
        return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
    }
}

Контроллер содержит два эндпоинта:

  • GET /api/users — возвращает список пользователей.
  • POST /api/users — добавляет нового пользователя.

Шаг 2: Настройка зависимостей в pom.xml

Добавим необходимые зависимости для тестирования:


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <scope>test</scope>
</dependency>

Шаг 3: Написание тестов для контроллера

Теперь создадим тестовый класс для UserController.

Импортируем нужные классы


import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

Настроим класс тестов


@WebMvcTest(UserController.class)
public class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    // Здесь мы будем писать тесты
}

Шаг 4: Тестирование GET /api/users

Напишем тест для проверки, что GET /api/users возвращает корректный список пользователей.


@Test
public void shouldReturnListOfUsers() throws Exception {
    // Создаем тестовые данные
    List<User> users = List.of(new User(1L, "John Doe"), new User(2L, "Jane Doe"));

    // Настраиваем поведение мока
    when(userService.findAll()).thenReturn(users);

    // Отправляем GET-запрос и проверяем результат
    mockMvc.perform(get("/api/users"))
           .andExpect(status().isOk())
           .andExpect(jsonPath("$.size()").value(users.size()))
           .andExpect(jsonPath("$[0].name").value("John Doe"))
           .andExpect(jsonPath("$[1].name").value("Jane Doe"));
}

Что здесь происходит:

  1. Создаем список пользователей для теста.
  2. Настраиваем мок userService, чтобы он возвращал этот список при вызове findAll().
  3. Делаем GET-запрос на /api/users.
  4. Проверяем:
    • Статус ответа (200 OK).
    • Размер списка в JSON-ответе.
    • Значение поля name у пользователей.

Шаг 5: Тестирование POST /api/users

Тестируем, что POST /api/users создаёт нового пользователя.


@Test
public void shouldCreateNewUser() throws Exception {
    // Создаем тестового пользователя
    User newUser = new User(null, "John Doe");
    User savedUser = new User(1L, "John Doe");

    // Настраиваем поведение мока
    when(userService.save(any(User.class))).thenReturn(savedUser);

    // Отправляем POST-запрос и проверяем результат
    mockMvc.perform(post("/api/users")
           .contentType(MediaType.APPLICATION_JSON)
           .content("{\"name\":\"John Doe\"}"))
           .andExpect(status().isCreated())
           .andExpect(jsonPath("$.id").value(1))
           .andExpect(jsonPath("$.name").value("John Doe"));
}

Здесь:

  1. Мы отправляем POST-запрос с JSON-объектом.
  2. Проверяем, что:
    • Статус ответа — 201 Created
    • Ответ содержит ID и имя нового пользователя.

Полезные советы

  1. Не забывайте про edge cases: тестируйте не только позитивные сценарии, но и негативные. Например, что происходит, если отправить некорректные данные.
  2. Используйте удобные методы: MockMvc предоставляет множество удобных методов, таких как jsonPath(), header() и т.д.
  3. Чистите после себя: пусть ваши тесты не полагаются на состояние предыдущих тестов. Каждый тест должен быть независимым.

Что дальше?

Теперь вы умеете тестировать REST-контроллеры с использованием MockMvc. Это не только полезно для обеспечения качества, но и отлично смотрится в резюме. В следующей лекции мы сосредоточимся на тестировании сервисов и репозиториев. А пока, вооружитесь знаниями и отправляйтесь тестировать свои контроллеры!

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ