REST Assured — Java-библиотека для HTTP-проверок с выразительным DSL. Она позволяет описывать запрос и проверять статус, заголовки и тело ответа. Обычно её используют вместе с JUnit Jupiter или другим runner, который управляет кейсами, подготовкой и итоговым результатом запуска.
Инструмент полезен в Java-команде: тесты могут использовать привычную сборку, типы данных и инфраструктуру. Но удобная цепочка given–when–then не определяет качество проверки. Для QA важны бизнес-ожидания, реальные границы интеграции и управляемое состояние системы.
Зависимости и выбранная версия
Пример рассчитан на Maven-проект с JDK 17+, зависимостью io.rest-assured:rest-assured:6.2.0 в test scope и настроенным запуском JUnit Jupiter. Документация REST Assured указывает эту версию на дату подготовки статьи. Версию runner и плагина сборки закрепите в проекте по их требованиям.
Не объявляйте автоматически любой новый релиз совместимым с существующим набором. Перед обновлением смотрят release notes, транзитивные зависимости и изменение API. Для учебного примера нужен стандартный модуль JDK jdk.httpserver; он создаёт локальный сервер без внешнего приложения.
Самостоятельная проверка HTTP-ответа
Сохраните класс как src/test/java/OrderApiTest.java и запустите mvn -Dtest=OrderApiTest test в подготовленном Maven-проекте. Сервер выбирает свободный порт и отвечает синтетическим заказом. Никакие реальные сервисы, базы или credentials не используются.
import com.sun.net.httpserver.HttpServer;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.equalTo;
class OrderApiTest {
@Test
void readsDraftOrder() throws Exception {
var server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
server.createContext("/orders/42", exchange -> {
byte[] body = "{\"id\":42,\"status\":\"draft\"}"
.getBytes(StandardCharsets.UTF_8);
exchange.getResponseHeaders().set("Content-Type", "application/json");
exchange.sendResponseHeaders(200, body.length);
try (var output = exchange.getResponseBody()) {
output.write(body);
}
});
server.start();
try {
given().baseUri("http://127.0.0.1")
.port(server.getAddress().getPort())
.when().get("/orders/42")
.then().statusCode(200)
.contentType("application/json")
.body("id", equalTo(42))
.body("status", equalTo("draft"));
} finally {
server.stop(0);
}
}
}Ожидается один успешный кейс. Изменение ожидаемого статуса заказа на paid должно дать содержательное падение проверки тела. Пример показывает технику HTTP-assertions; он не доказывает работу сервиса заказов, поскольку ответ намеренно сформирован локальным fixture.
Что означает цепочка DSL
given задаёт параметры запроса: URL, headers, тело и аутентификацию. when выполняет действие. then проверяет полученный ответ. Такая структура помогает видеть предусловия и результат, но не должна превращаться в длинную цепь несвязанных проверок.
Разделяйте обязательный контракт и важные бизнес-поля. Проверить весь JSON дословно бывает слишком хрупко, если ответ содержит время и технические метаданные. Но проверять только наличие поля тоже слабо: заказ с чужим ownerId останется незамеченным.
Подготовка данных и реальные операции
В тестовом сервисе создайте отдельную корзину с двумя товарами по 5 000 денежных единиц. Примените согласованный купон десять процентов. Ожидайте итог 9 000, идентификатор своей корзины и корректное сохранённое состояние после повторного чтения.
Негативный кейс отправляет неизвестный купон и проверяет предусмотренный код ошибки, причину и неизменную сумму. Статусы и округление берут из контракта продукта. Случайное ожидание «любая ошибка 4xx» пропустит подмену валидации ошибкой доступа.
Проверку владения выполняйте отдельными клиентами двух ролей. Владелец читает созданный заказ, другой пользователь обращается к тому же ID и получает предусмотренный отказ без чужих данных. Следующая операция первого пользователя должна по-прежнему работать. Такое чередование помогает увидеть случайное смешивание credentials или серверного контекста. Очистка использует точный идентификатор и права владельца тестовых данных, а не общий запрос удаления всех заказов. Для параллельного запуска сохраняйте связь каждого ресурса с конкретным прогоном и проверяйте результат подготовки до начала основного assertion.
RequestSpecification и повторение
RequestSpecification помогает собрать общие настройки: базовый адрес, тип содержимого, безопасные headers и фильтры. Храните в ней техническую конфигурацию, а данные конкретного сценария передавайте явно. Это уменьшает повторение, сохраняя читабельность запроса.
Изменяемая глобальная конфигурация усложняет понимание параллельного выполнения и смены ролей. Даже если конкретная версия улучшает потокобезопасность внутренних механизмов, общие credentials или объекты данных всё равно способны смешать сценарии. Предпочитайте явную локальную спецификацию и изолированные сущности.
JSON Schema и смысл данных
Проверка схемы помогает контролировать обязательность и типы полей. Для неё используется отдельный модуль json-schema-validator и схема поддерживаемого выбранной версией формата. Проверяйте возможности версии, прежде чем копировать схему из другого проекта.
Схема не подтверждает корректную стоимость, доступ к ресурсу или переход статуса. Комбинируйте структурные assertions с конкретными бизнес-ожиданиями. При работе с десятичными значениями учитывайте представление чисел и используйте подходящий тип или matcher, а не случайное сравнение float.
Наблюдение асинхронного результата
Принятый HTTP-запрос может только поставить задачу в очередь. Если контракт обещает отложенный результат, проверка должна наблюдать его через согласованную границу: статус операции, событие или повторное чтение. Ожидание ограничивают временем и сохраняют последний ответ для диагностики.
Не отправляйте создание заказа заново в каждом цикле ожидания. Повторяют безопасное наблюдение уже созданной операции. Идемпотентность запроса проверяют отдельным сценарием с предусмотренным механизмом, а не предполагают на основании используемого HTTP-метода.
Логи и расследование
Полезный отказ показывает метод, безопасный адрес, ожидаемое и фактическое поле, код ответа и идентификатор операции. Логирование только при ошибке уменьшает шум, но фильтры должны исключать токены, cookie и чувствительные payload.
Если сервер отвечает HTML вместо JSON, сначала исследуют маршрут, redirect, proxy и авторизацию. Ошибка парсинга является симптомом. Нельзя автоматически лечить её изменением JSON-пути или разрешением любого content type: это может скрыть настоящий дефект интеграции.
Ошибки и рабочие выводы
Частые проблемы: сравнение только status 200, общий заказ на весь набор, скрытая смена ролей и предположение, что успешная десериализация равна корректному ответу. Не отключайте TLS-проверку для любого окружения: сначала установите причину проблемы сертификата и согласованный тестовый trust store.
REST Assured даёт удобный язык HTTP-проверок. Надёжность появляется из ясного контракта, независимых данных и проверки последствий. Начните с небольшого воспроизводимого сценария и расширяйте набор по рискам сервиса, сохраняя понятные причины каждого assertion.
При добавлении кейса укажите, какой новый риск он контролирует: ещё один успешный запрос не обязательно расширяет полезное покрытие сервиса.