Тестирование API REST с Java

Протестируйте REST API с помощью Java

1. обзор

В этом руководстве основное внимание уделяется основным принципам и механикеtesting a REST API with live Integration Tests (с полезной нагрузкой JSON).

# # Основная цель - предоставить введение в тестирование базовой правильности API - и мы собираемся использовать последнюю версиюGitHub REST API для примеров.

Для внутреннего приложения этот вид тестирования обычно выполняется в качестве позднего шага в процессе непрерывной интеграции, потребляя REST API после того, как он уже развернут.

При тестировании ресурса REST обычно есть несколько ортогональных обязанностей, на которых должны сосредоточиться тесты:

  • HTTPresponse code

  • другой HTTPheaders в ответе

  • payload (JSON, XML)

Each test should only focus on a single responsibility and include a single assertion. Сосредоточение внимания на четком разделении всегда имеет преимущества, но при проведении такого рода тестирования черного ящика это еще более важно, поскольку общая тенденция заключается в написании сложных сценариев тестирования в самом начале.

Еще один важный аспект интеграционных тестов - соблюдениеSingle Level of Abstraction Principle - логика внутри теста должна быть написана на высоком уровне. Такие детали, как создание запроса, отправка HTTP-запроса на сервер, работа с IO и т. Д., Должны выполняться не встроенно, а с помощью служебных методов.

Дальнейшее чтение:

Интеграционное тестирование весной

Краткое руководство по написанию интеграционных тестов для веб-приложения Spring.

Read more

Тестирование в Spring Boot

Узнайте, как Spring Boot поддерживает тестирование, чтобы эффективно писать модульные тесты.

Read more

Руководство по гарантированному отдыху

Изучите основы REST-гарантированной - библиотеки, которая упрощает тестирование и проверку REST API.

Read more

2. Проверка кода состояния

@Test
public void givenUserDoesNotExists_whenUserInfoIsRetrieved_then404IsReceived()
  throws ClientProtocolException, IOException {

    // Given
    String name = RandomStringUtils.randomAlphabetic( 8 );
    HttpUriRequest request = new HttpGet( "https://api.github.com/users/" + name );

    // When
    HttpResponse httpResponse = HttpClientBuilder.create().build().execute( request );

    // Then
    assertThat(
      httpResponse.getStatusLine().getStatusCode(),
      equalTo(HttpStatus.SC_NOT_FOUND));
}

Это довольно простой тест -it verifies that a basic happy path is working, не усложняющий набор тестов.

Если по какой-либо причине он не работает, то нет необходимости искать какой-либо другой тест для этого URL, пока он не будет исправлен.

3. Проверка типа носителя

@Test
public void
givenRequestWithNoAcceptHeader_whenRequestIsExecuted_thenDefaultResponseContentTypeIsJson()
  throws ClientProtocolException, IOException {

   // Given
   String jsonMimeType = "application/json";
   HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );

   // When
   HttpResponse response = HttpClientBuilder.create().build().execute( request );

   // Then
   String mimeType = ContentType.getOrDefault(response.getEntity()).getMimeType();
   assertEquals( jsonMimeType, mimeType );
}

Это гарантирует, что ответ действительно содержит данные JSON.

Как вы могли заметить,we’re following a logical progression of tests - сначала код состояния ответа (чтобы убедиться, что запрос был в порядке), затем тип носителя ответа, и только в следующем тесте мы рассмотрим фактическую полезную нагрузку JSON.

4. Тестирование полезной нагрузки JSON

@Test
public void
  givenUserExists_whenUserInformationIsRetrieved_thenRetrievedResourceIsCorrect()
  throws ClientProtocolException, IOException {

    // Given
    HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );

    // When
    HttpResponse response = HttpClientBuilder.create().build().execute( request );

    // Then
    GitHubUser resource = RetrieveUtil.retrieveResourceFromResponse(
      response, GitHubUser.class);
    assertThat( "eugenp", Matchers.is( resource.getLogin() ) );
}

В этом случае я знаю, что по умолчанию ресурсы GitHub представлены в формате JSON, но обычно заголовок ответа `++`Content-Type должен тестироваться вместе с заголовкомAccept запроса - клиент спрашивает для определенного типа представления черезAccept, который сервер должен соблюдать.

5. Утилиты для тестирования

Мы собираемся использовать Jackson 2 для демаршалинга необработанной строки JSON в типобезопасный объект Java:

public class GitHubUser {

    private String login;

    // standard getters and setters
}

Мы используем только простую утилиту, чтобы тесты были чистыми, удобочитаемыми и имели высокий уровень абстракции:

public static  T retrieveResourceFromResponse(HttpResponse response, Class clazz)
  throws IOException {

    String jsonFromResponse = EntityUtils.toString(response.getEntity());
    ObjectMapper mapper = new ObjectMapper()
      .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    return mapper.readValue(jsonFromResponse, clazz);
}

Обратите внимание наJackson is ignoring unknown properties, которые API GitHub отправляет нам - это просто потому, что представление пользовательского ресурса на GitHub становится довольно сложным - и нам здесь не нужна эта информация.

6. зависимости

Утилиты и тесты используют следующие библиотеки, все доступные в Maven central:

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

Это только одна часть того, каким должен быть полный комплект тестирования интеграции. Тесты сосредоточены наensuring basic correctness for the REST API, не вдаваясь в более сложные сценарии,

Например, не рассматриваются следующие вопросы: обнаружение API, использование разных представлений для одного и того же ресурса и т. Д.

[.iframe-fluid] ##

Реализация всех этих примеров и фрагментов кода можно найти вover on Github - это проект на основе Maven, поэтому его должно быть легко импортировать и запускать как есть.