Рубрики
Без рубрики

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

Как протестировать REST – сервис с помощью Java – integration testing с помощью Http-клиента Apache.

Автор оригинала: Eugen Paraschiv.

1. Обзор

Этот учебник посвящен основным принципам и механике тестирования REST API с помощью live Integration Tests (с полезной нагрузкой JSON).

Основная цель состоит в том, чтобы дать введение в тестирование базовой корректности API – и мы будем использовать последнюю версию GitHub REST API для примеров.

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

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

  • код ответа HTTP
  • другие HTTP заголовки в ответе
  • полезная нагрузка (JSON, XML)

Каждый тест должен фокусироваться только на одной ответственности и включать в себя одно утверждение. Фокусировка на четком разделении всегда имеет преимущества, но при выполнении такого рода тестирования черного ящика еще более важно, так как общая тенденция заключается в написании сложных тестовых сценариев в самом начале.

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

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

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

Тестирование в весеннем ботинке

Руководство для того, чтобы быть уверенным в себе

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));
}

Это довольно простой тест – он проверяет , что базовый счастливый путь работает , не добавляя слишком много сложности в набор тестов.

Если по какой-либо причине он не работает, то нет необходимости искать какой-либо другой тест для этого 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.

Как вы могли заметить, мы следуем логической последовательности тестов – сначала код состояния ответа (чтобы убедиться, что запрос был в порядке), затем тип носителя ответа, и только в следующем тесте мы посмотрим на фактическую полезную нагрузку 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);
}

Обратите внимание, что Джексон игнорирует неизвестные свойства, которые API GitHub посылает нам – это просто потому, что представление пользовательского ресурса на GitHub становится довольно сложным, – и нам здесь не нужна эта информация.

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

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

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

Это только одна часть того, чем должен быть полный комплект интеграционного тестирования. Тесты фокусируются на обеспечении базовой корректности для REST API , не вдаваясь в более сложные сценарии,

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

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