Как тестировать REST API статус код
Что проверяют
Умеете ли вы писать тесты на HTTP-слой и понимаете ли, какой код в каком случае должен вернуться. Следом часто спрашивают, чем 401 отличается от 403 и как проверить, что ошибка валидации отдаёт 400, а не 500.
Как отвечать
Сначала уточните, о чём речь: о своём контроллере на Spring Boot или о чужом API, которое тестируется снаружи. Инструменты разные.
- свой контроллер, срез веб-слоя:
@WebMvcTestподнимает только MVC-часть, сервисы подменяются через@MockitoBean(в Spring Boot 3.4 он пришёл на смену устаревшему@MockBean). Проверка:mockMvc.perform(get("/users/42")).andExpect(status().isNotFound()). Для реактивного стекаWebTestClientиexpectStatus(); - полный контекст:
@SpringBootTest(webEnvironment = RANDOM_PORT)и настоящий HTTP-клиент, тогда в тест попадают фильтры, Spring Security и обработчики ошибок; - внешний API: REST Assured,
given().body(dto).when().post("/orders").then().statusCode(201), плюс проверки тела и заголовков в той же цепочке; - какие коды проверять: 201 с заголовком
Locationна создание, 204 на удаление, 400 на невалидный вход, 401 без токена, 403 с токеном без прав, 404 на несуществующий ресурс, 409 на конфликт. Негативных сценариев обычно больше, чем позитивных.
Хорошо добавить, откуда код берётся: @ExceptionHandler в @RestControllerAdvice, ResponseStatusException, а для тела ошибки ProblemDetail (формат RFC 9457), который Spring поддерживает из коробки.
Где спотыкаются
Используют ключевое слово assert, как в примерах из интернета. В JVM оно по умолчанию выключено и без флага -ea не проверяет ничего, тест всегда зелёный. Нужны assertEquals из JUnit или AssertJ.
Проверяют только статус. Ответ 200 с телом {"error": "..."} проходит такой тест, поэтому код ответа всегда дополняют проверкой тела и схемы.
Путают 401 и 403 или ожидают 500 как «нормальный» ответ на кривой запрос. 500 в тесте означает необработанное исключение, это баг сервиса, а не ожидаемое поведение.