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

Введение в WireMock

Краткое и практическое руководство по удалению API-интерфейсов REST с помощью WireMock.

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

1. Обзор

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

Когда WireMock сервер в действии, мы можем настроить ожидания, вызвать службу, а затем проверить ее поведение.

2. Зависимости Maven

Чтобы иметь возможность воспользоваться преимуществами библиотеки WireMock, нам необходимо включить в POM следующую зависимость:


    com.github.tomakehurst
    wiremock
    1.58
    test

3. Сервер с программным Управлением

В этом разделе будет рассмотрен способ ручной настройки сервера WireMock, т. е. без поддержки автоматической настройки JUnit. Использование демонстрируется очень простой заглушкой.

3.1. Настройка Сервера

Сервер WireMock может быть создан следующим образом:

WireMockServer wireMockServer = new WireMockServer(String host, int port);

В случае, если аргументы не указаны, хост сервера по умолчанию имеет значение localhost , а порт сервера – 8080 .

Затем сервер может быть запущен и остановлен двумя простыми способами:

wireMockServer.start();

И:

wireMockServer.stop();

3.2. Основное использование

Библиотека WireMock будет сначала продемонстрирована с помощью базового использования, где предоставляется заглушка для точного URL-адреса без какой-либо дополнительной настройки. Давайте создадим экземпляр сервера:

WireMockServer wireMockServer = new WireMockServer();

Сервер WireMock должен быть запущен до того, как клиент подключится к нему:

wireMockServer.start();

Затем веб-служба отключается:

configureFor("localhost", 8080);
stubFor(get(urlEqualTo("/baeldung")).willReturn(aResponse().withBody("Welcome to Baeldung!")));

В этом руководстве используется API Apache HttpClient для представления клиента, подключающегося к серверу:

CloseableHttpClient httpClient = HttpClients.createDefault();

Запрос выполняется, а затем, соответственно, возвращается ответ:

HttpGet request = new HttpGet("http://localhost:8080/baeldung");
HttpResponse httpResponse = httpClient.execute(request);

Мы преобразуем переменную http-ответа в Строку с помощью вспомогательного метода:

String responseString = convertResponseToString(httpResponse);

Вот реализация этого вспомогательного метода преобразования:

private String convertResponseToString(HttpResponse response) throws IOException {
    InputStream responseStream = response.getEntity().getContent();
    Scanner scanner = new Scanner(responseStream, "UTF-8");
    String responseString = scanner.useDelimiter("\\Z").next();
    scanner.close();
    return responseString;
}

Следующий код проверяет, что сервер получил запрос на ожидаемый URL-адрес, и ответ, поступающий клиенту, является именно тем, что было отправлено:

verify(getRequestedFor(urlEqualTo("/baeldung")));
assertEquals("Welcome to Baeldung!", stringResponse);

Наконец, сервер WireMock следует остановить, чтобы освободить системные ресурсы:

wireMockServer.stop();

4. Управляемый сервер JUnit

В отличие от раздела 3, этот раздел иллюстрирует использование WireMockserver с помощью JUnit Правила .

4.1. Настройка Сервера

Сервер WireMock может быть интегрирован в тестовые случаи JUnit с помощью аннотации @Rule . Это позволяет JUnit управлять жизненным циклом, запуская сервер перед каждым методом тестирования и останавливая его после возврата метода.

Подобно программно управляемому серверу, управляемый JUnit WireMockserver может быть создан как объект Java с заданным номером порта:

@Rule
public WireMockRule wireMockRule = new WireMockRule(int port);

Если аргументы не указаны, порт сервера примет значение по умолчанию, 8080 . Хост сервера, по умолчанию localhost и другие конфигурации могут быть указаны с помощью интерфейса Параметры .

4.2. Сопоставление URL-адресов

После настройки Экземпляр WireMockRule , следующим шагом является настройка заглушки. В этом подразделе мы предоставим заглушку REST для конечной точки службы с использованием регулярного выражения:

stubFor(get(urlPathMatching("/baeldung/.*"))
  .willReturn(aResponse()
  .withStatus(200)
  .withHeader("Content-Type", "application/json")
  .withBody("\"testing-library\": \"WireMock\"")));

Давайте перейдем к созданию HTTP-клиента, выполнению запроса и получению ответа:

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet request = new HttpGet("http://localhost:8080/baeldung/wiremock");
HttpResponse httpResponse = httpClient.execute(request);
String stringResponse = convertHttpResponseToString(httpResponse);

Приведенный выше фрагмент кода использует преимущества вспомогательного метода преобразования:

private String convertHttpResponseToString(HttpResponse httpResponse) throws IOException {
    InputStream inputStream = httpResponse.getEntity().getContent();
    return convertInputStreamToString(inputStream);
}

Это, в свою очередь, использует другой частный метод:

private String convertInputStreamToString(InputStream inputStream) {
    Scanner scanner = new Scanner(inputStream, "UTF-8");
    String string = scanner.useDelimiter("\\Z").next();
    scanner.close();
    return string;
}

Операции заглушки проверяются с помощью приведенного ниже кода тестирования:

verify(getRequestedFor(urlEqualTo("/baeldung/wiremock")));
assertEquals(200, httpResponse.getStatusLine().getStatusCode());
assertEquals("application/json", httpResponse.getFirstHeader("Content-Type").getValue());
assertEquals("\"testing-library\": \"WireMock\"", stringResponse);

4.3. Соответствие Заголовка Запроса

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

stubFor(get(urlPathEqualTo("/baeldung/wiremock"))
  .withHeader("Accept", matching("text/.*"))
  .willReturn(aResponse()
  .withStatus(503)
  .withHeader("Content-Type", "text/html")
  .withBody("!!! Service Unavailable !!!")));

Аналогично предыдущему подразделу, мы проиллюстрируем взаимодействие HTTP с использованием API HttpClient с помощью тех же вспомогательных методов:

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet request = new HttpGet("http://localhost:8080/baeldung/wiremock");
request.addHeader("Accept", "text/html");
HttpResponse httpResponse = httpClient.execute(request);
String stringResponse = convertHttpResponseToString(httpResponse);

Следующие проверки и утверждения подтверждают функции заглушки, которую мы создали ранее:

verify(getRequestedFor(urlEqualTo("/baeldung/wiremock")));
assertEquals(503, httpResponse.getStatusLine().getStatusCode());
assertEquals("text/html", httpResponse.getFirstHeader("Content-Type").getValue());
assertEquals("!!! Service Unavailable !!!", stringResponse);

4.4. Соответствие Тела Запроса

Библиотеку WireMock также можно использовать для заглушки API REST с сопоставлением тела. Вот конфигурация для заглушки такого рода:

stubFor(post(urlEqualTo("/baeldung/wiremock"))
  .withHeader("Content-Type", equalTo("application/json"))
  .withRequestBody(containing("\"testing-library\": \"WireMock\""))
  .withRequestBody(containing("\"creator\": \"Tom Akehurst\""))
  .withRequestBody(containing("\"website\": \"wiremock.org\""))
  .willReturn(aResponse()
  .withStatus(200)));

Теперь пришло время создать Строковую сущность объект, который будет использоваться в качестве тела запроса:

InputStream jsonInputStream 
  = this.getClass().getClassLoader().getResourceAsStream("wiremock_intro.json");
String jsonString = convertInputStreamToString(jsonInputStream);
StringEntity entity = new StringEntity(jsonString);

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

Вот содержимое файла wiremock_intro.json в пути к классу:

{
    "testing-library": "WireMock",
    "creator": "Tom Akehurst",
    "website": "wiremock.org"
}

HTTP-запросы и ответы могут быть настроены и выполнены следующим образом:

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost request = new HttpPost("http://localhost:8080/baeldung/wiremock");
request.addHeader("Content-Type", "application/json");
request.setEntity(entity);
HttpResponse response = httpClient.execute(request);

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

verify(postRequestedFor(urlEqualTo("/baeldung/wiremock"))
  .withHeader("Content-Type", equalTo("application/json")));
assertEquals(200, response.getStatusLine().getStatusCode());

4.5. Приоритет заглушки

В предыдущих подразделах рассматриваются ситуации, когда HTTP-запрос соответствует только одной заглушке. Это было бы сложнее, если бы для запроса было больше, чем совпадение. По умолчанию в таком случае приоритет будет иметь последний добавленный заглушка. Однако пользователям разрешается настраивать это поведение, чтобы в большей степени контролировать заглушки WireMock.

Мы продемонстрируем работу сервера WireMock, когда поступающий запрос соответствует двум различным настройкам, с одновременной установкой уровня приоритета и без него. В обоих сценариях будет использоваться следующий частный вспомогательный метод:

private HttpResponse generateClientAndReceiveResponseForPriorityTests() throws IOException {
    CloseableHttpClient httpClient = HttpClients.createDefault();
    HttpGet request = new HttpGet("http://localhost:8080/baeldung/wiremock");
    request.addHeader("Accept", "text/xml");
    return httpClient.execute(request);
}

Во – первых, настройте две заглушки без учета уровня приоритета:

stubFor(get(urlPathMatching("/baeldung/.*"))
  .willReturn(aResponse()
  .withStatus(200)));
stubFor(get(urlPathEqualTo("/baeldung/wiremock"))
  .withHeader("Accept", matching("text/.*"))
  .willReturn(aResponse()
  .withStatus(503)));

Затем создайте HTTP-клиент и выполните запрос, используя вспомогательный метод, описанный выше:

HttpResponse httpResponse = generateClientAndReceiveResponseForPriorityTests();

Следующий фрагмент кода проверяет, что последняя настроенная заглушка применяется независимо от заданной ранее, когда запрос соответствует им обоим:

verify(getRequestedFor(urlEqualTo("/baeldung/wiremock")));
assertEquals(503, httpResponse.getStatusLine().getStatusCode());

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

stubFor(get(urlPathMatching("/baeldung/.*"))
  .atPriority(1)
  .willReturn(aResponse()
  .withStatus(200)));
stubFor(get(urlPathEqualTo("/baeldung/wiremock"))
  .atPriority(2)
  .withHeader("Accept", matching("text/.*"))
  .willReturn(aResponse()
  .withStatus(503)));

Создание и выполнение HTTP-запроса:

HttpResponse httpResponse = generateClientAndReceiveResponseForPriorityTests();

Следующий код проверяет влияние уровней приоритета, когда вместо последнего применяется первая настроенная заглушка:

verify(getRequestedFor(urlEqualTo("/baeldung/wiremock")));
assertEquals(200, httpResponse.getStatusLine().getStatusCode());

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

В этом учебном пособии рассказывается о WireMock и о том, как настроить и настроить эту библиотеку для тестирования API-интерфейсов REST с использованием различных методов, включая сопоставление URL-адреса, заголовков запросов и тела.

Реализацию всех примеров и фрагментов кода можно найти в проекте GitHub .