«1. Обзор

В этом руководстве мы обсудим, как тестировать службы REST с использованием REST-assured, уделяя особое внимание сбору и проверке данных ответа от наших API-интерфейсов REST.

2. Настройка для тестового класса

В предыдущих руководствах мы рассмотрели REST-assured в целом и показали, как манипулировать заголовками запросов, файлами cookie и параметрами.

Опираясь на эту существующую настройку, мы добавили простой контроллер REST, AppController, который внутренне вызывает службу AppService. Мы будем использовать эти классы в наших тестовых примерах.

Чтобы создать наш тестовый класс, нам нужно немного больше настроить. Поскольку у нас есть spring-boot-starter-test в нашем пути к классам, мы можем легко использовать утилиты тестирования Spring.

Во-первых, давайте создадим скелет нашего класса AppControllerIntegrationTest:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class AppControllerIntegrationTest {

    @LocalServerPort
    private int port;

    private String uri;

    @PostConstruct
    public void init() {
        uri = "http://localhost:" + port;
    }

    @MockBean
    AppService appService;

     //test cases
}

В этом тесте JUnit мы аннотировали наш класс парой специфичных для Spring аннотаций, которые запускают приложение локально в случайном доступном порт. В @PostConstruct мы зафиксировали полный URI, по которому будем совершать вызовы REST.

Мы также использовали @MockBean в AppService, так как нам нужно имитировать вызовы методов этого класса.

3. Проверка ответа JSON

JSON является наиболее распространенным форматом, используемым в REST API для обмена данными. Ответы могут состоять из одного объекта JSON или массива объектов JSON. Мы рассмотрим оба в этом разделе.

3.1. Один объект JSON

Допустим, нам нужно протестировать конечную точку /movie/{id}, которая возвращает объект Movie JSON, если идентификатор найден.

Мы смоделируем вызовы AppService, чтобы вернуть некоторые фиктивные данные, используя инфраструктуру Mockito:

@Test
public void givenMovieId_whenMakingGetRequestToMovieEndpoint_thenReturnMovie() {

    Movie testMovie = new Movie(1, "movie1", "summary1");
    when(appService.findMovie(1)).thenReturn(testMovie);

    get(uri + "/movie/" + testMovie.getId()).then()
      .assertThat()
      .statusCode(HttpStatus.OK.value())
      .body("id", equalTo(testMovie.getId()))
      .body("name", equalTo(testMovie.getName()))
      .body("synopsis", notNullValue());
}

Выше мы сначала смоделировали вызов appService.findMovie(1) для возврата объекта. Затем мы создали наш URL-адрес REST в методе get(), предоставленном REST-assured для выполнения запросов GET. Наконец, мы сделали четыре утверждения.

Сначала мы проверили код состояния ответа, а затем элементы тела. Мы используем Hamcrest для утверждения ожидаемого значения.

Также обратите внимание, что если ответ JSON является вложенным, мы можем проверить вложенный ключ, используя оператор точки, например «key1.key2.key3».

3.2. Извлечение ответа JSON после проверки

В некоторых случаях нам может потребоваться извлечь ответ после проверки, чтобы выполнить над ним дополнительные операции.

Мы можем извлечь ответ JSON для класса с помощью метода extract():

Movie result = get(uri + "/movie/" + testMovie.getId()).then()
  .assertThat()
  .statusCode(HttpStatus.OK.value())
  .extract()
  .as(Movie.class);
assertThat(result).isEqualTo(testMovie);

В этом примере мы указали REST-assured для извлечения ответа JSON на объект Movie, а затем утвердили извлеченный объект.

Мы также можем извлечь весь ответ на строку, используя API extract().asString():

String responseString = get(uri + "/movie/" + testMovie.getId()).then()
  .assertThat()
  .statusCode(HttpStatus.OK.value())
  .extract()
  .asString();
assertThat(responseString).isNotEmpty();

Наконец, мы также можем извлечь конкретное поле из ответа JSON.

Давайте рассмотрим тест для POST API, который ожидает тело фильма в формате JSON и возвращает его при успешной вставке:

@Test
public void givenMovie_whenMakingPostRequestToMovieEndpoint_thenCorrect() {
    Map<String, String> request = new HashMap<>();
    request.put("id", "11");
    request.put("name", "movie1");
    request.put("synopsis", "summary1");

    int movieId = given().contentType("application/json")
      .body(request)
      .when()
      .post(uri + "/movie")
      .then()
      .assertThat()
      .statusCode(HttpStatus.CREATED.value())
      .extract()
      .path("id");
    assertThat(movieId).isEqualTo(11);
}

Выше мы сначала создали объект запроса, который нам нужен для POST. Затем мы извлекли поле id из возвращенного ответа JSON, используя метод path().

3.3. Массив JSON

Мы также можем проверить ответ, если это массив JSON:

@Test
public void whenCallingMoviesEndpoint_thenReturnAllMovies() {

Set<Movie> movieSet = new HashSet<>();
movieSet.add(new Movie(1, "movie1", "summary1"));
movieSet.add(new Movie(2, "movie2", "summary2"));
when(appService.getAll()).thenReturn(movieSet);

get(uri + "/movies").then()
    .statusCode(HttpStatus.OK.value())
    .assertThat()
    .body("size()", is(2));
}

Мы снова сначала смоделировали appService.getAll() с некоторыми данными и сделали запрос к нашей конечной точке. Затем мы утвердили statusCode и размер нашего массива ответов.

Это снова можно сделать с помощью извлечения:

Movie[] movies = get(uri + "/movies").then()
  .statusCode(200)
  .extract()
  .as(Movie[].class);
assertThat(movies.length).isEqualTo(2);

4. Проверка заголовков и файлов cookie

Мы можем проверить заголовок или файл cookie ответа, используя методы с тем же именем:

@Test
public void whenCallingWelcomeEndpoint_thenCorrect() {
    get(uri + "/welcome").then()
        .assertThat()
        .header("sessionId", notNullValue())
        .cookie("token", notNullValue());
}

Мы также можно извлекать заголовки и файлы cookie по отдельности:

Response response = get(uri + "/welcome");

String headerName = response.getHeader("sessionId");
String cookieValue = response.getCookie("token");
assertThat(headerName).isNotBlank();
assertThat(cookieValue).isNotBlank();

5. Проверка файлов

Если наш REST API возвращает файл, мы можем использовать метод asByteArray() для извлечения ответа:

File file = new ClassPathResource("test.txt").getFile();
long fileSize = file.length();
when(appService.getFile(1)).thenReturn(file);

byte[] result = get(uri + "/download/1").asByteArray();

assertThat(result.length).isEqualTo(fileSize);

Здесь , мы сначала имитировали appService.getFile(1), чтобы вернуть текстовый файл, который присутствует в нашем пути src/test/resources. Затем мы сделали вызов нашей конечной точке и извлекли ответ в byte[], который, как мы утверждали, имеет ожидаемое значение.

6. Заключение

В этом руководстве мы рассмотрели различные способы сбора и проверки ответов от наших REST API с использованием REST-assured.

Как обычно, код этой статьи доступен на Github.