В этой статье показаны самые простые примеры использования библиотеки REST-assured.
Что тестируем
Тестировать будем простое Spring Boot приложение — то же, что и в предыдущей статье о TestRestTemplate. Приложение предоставляет RESTfull API для сущности Person:
@Entity public class Person { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @NotNull private String name; // setters/getters }
Подробнее о создании приложение читайте в руководстве. Сразу скажу, что в приложении мы используем встроенную базу h2 db, чтобы не устанавливать внешнюю базу данных.
Базу мы очищаем после каждого теста, чтобы все было понятно — каждый тест начинается с пустой базы, в которую при необходимости мы добавляем одного или двоих Person.
Maven-зависимость
Чтобы использовать библиотеку REST-assured, включите в проект зависимость:
<dependency> <groupId>io.rest-assured</groupId> <artifactId>rest-assured</artifactId> <version>3.1.0</version> <scope>test</scope> </dependency>
Последняя версия доступна здесь.
Тестирование добавления — POST
Запись в базу мы добавляем с мопощью такого POST-запроса:
POST /persons
При этом в теле передается Person в формате JSON:
{ "id": null, "name": "Michail" }
В ответ мы должны получить вновь созданного Person в формате JSON и статус 201 (created).
Протестируем и убедимся, что все так и есть:
@Test public void whenCreatePerson_thenStatus201() { Person person = new Person("Michail"); given().log().body() .contentType("application/json").body(person) .when().post("/persons") .then().log().body() .statusCode(HttpStatus.CREATED.value()); }
given(), when() и then()
Тест REST-assured состоит из трех частей:
- given() задает предварительные условия запроса. Здесь это content-type (мы задали формат JSON), логирование и тело запроса.
Логирование мы включили для учебных целей. Благодаря log().body() мы увидим в консоли тело посланного запроса.
Тело запроса задано в методе body(person). То есть в теле будет Person в JSON-формате.
Вообще часть given() необязательна, но чаще она есть. - when() — тут мы говорим, что это POST-запрос по адресу /persons
- then() — тут происходит само тестирование.
Мы снова логируем, но уже тело ответа.
И проверяем, что код ответа равен 201.
Тестирование редактирования — PUT
Следующий запрос — для редактирования Person:
PUT /persons/{id}
В теле запроса снова передается Person в формате JSON с заданным id:
{ "id": 1, "name": "Michail" }
Тестирование выглядит так (в начале теста мы создаем тестовый Person и берем его id, чтоб отредактировать сущность по адресу /persons/{id}:
@Test public void whenUpdatePerson_thenStatus200() { long id = createTestPerson("Nick").getId(); Person person = new Person("Michail"); given().pathParam("id", id).log() .body().contentType("application/json").body(person) .when().put("/persons/{id}") .then().log().body().statusCode(HttpStatus.OK.value()) .and().body("name", equalTo("Michail")); }
Тут присутствует метод pathParam(«id», id) — на место id в пути /persons/id мы подставляем реальное значение id того Person, которого мы хотим отредактировать.
Также мы тестируем тело JSON-ответа — проверяем, что name действительно равно Michail.
Тестирование удаления — DELETE
Запрос выглядит так:
DELETE /persons/{id}
В теле запроса ничего не передается.
Возвращается JSON удаленного Person:
{ "id": 1, "name": "Nick" }
Протестируем. В начале метода мы снова создаем Person, которого будем удалять, и берем его id:
@Test public void givenPerson_whenDeletePerson_thenStatus200() { long id = createTestPerson("Nick").getId(); given().pathParam("id", id).log().body().contentType("application/json") .when().delete("/persons/{id}") .then().log().body() .statusCode(HttpStatus.OK.value()).and().body("name", equalTo("Nick")); }
Мы логируем тело ответа и проверяем, что его имя равно Nick.
Еще, как обычно, проверяем код ответа.
Тестирование получения — GET
GET /persons
Здесь ничего нового, единственное — метод get():
@Test public void givenPerson_whenGetPerson_thenStatus200() { long id = createTestPerson("Joe").getId(); given().pathParam("id", id) .when().get("/persons/{id}") .then().log().body().statusCode(HttpStatus.OK.value()) .and().body("name", equalTo("Joe")); }
А теперь попробуем получить Person, которого не существует. Для этого просто не создаем его в начале метода, ведь база пуста:
@Test public void givenNoPerson_whenGetPerson_thenStatus500() { given().pathParam("id", 1) .when().get("/persons/{id}") .then().log().body() .statusCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); }
По умолчанию Spring выдает код ответа 500, так как контроллер выбрасывает исключение, которое мы в приложении никак не обрабатываем. Действительно, мы получили код ответа 500.
Тестирование получения списка — GET
GET /persons
[ { "id": 1, "name": "Joe" }, { "id": 2, "name": "Jane" } ]
В начале теста создадим два элемента.
Проверим, что при запросе списка возвращается код ответа 200, и каждый элемент имеет соответствующее имя:
@Test public void givenPersons_whenGetPersons_thenStatus200() { createTestPerson("Joe"); createTestPerson("Jane"); when().get("/persons") .then().log().body() .statusCode(HttpStatus.OK.value()) .and().body("get(0).name", equalTo("Joe")) .and().body("get(1).name", equalTo("Jane")); }
Обратите внимание, что для получения элементов списка используются команды get(0), get(1)
Итог
REST-assured — удобная библиотека, ее стоит использовать.
Исходный код проекта находится на GitHub.