Тестирование с REST-assured

В этой статье показаны самые простые примеры использования библиотеки 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.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *