Перейти к основному содержимому

Использование сценариев WireMock

· 4 мин. чтения

1. Обзор

В этом кратком руководстве показано, как мы можем протестировать HTTP-API с отслеживанием состояния с помощью WireMock .

Чтобы начать работу с библиотекой, сначала ознакомьтесь с нашим руководством Introduction to WireMock .

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

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

<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>2.21.0</version>
<scope>test</scope>
</dependency>

3. Пример API, который мы хотим смоделировать

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

Чтобы проиллюстрировать это, мы рассмотрим практический пример: сервис «Java Tip», который дает нам разные советы о Java всякий раз, когда мы запрашиваем его конечную точку /java-tip .

Если мы попросим чаевые, мы вернем их в text/plain :

"use composition rather than inheritance"

Если бы мы позвонили туда еще раз, то получили бы другой совет.

4. Создание состояний сценария

Нам нужно, чтобы WireMock создавал заглушки для конечной точки «/java-tip» . Каждая заглушка будет возвращать определенный текст, который соответствует одному из 3 состояний фиктивного API:

public class WireMockScenarioExampleIntegrationTest {
private static final String THIRD_STATE = "third";
private static final String SECOND_STATE = "second";
private static final String TIP_01 = "finally block is not called when System.exit()"
+ " is called in the try block";
private static final String TIP_02 = "keep your code clean";
private static final String TIP_03 = "use composition rather than inheritance";
private static final String TEXT_PLAIN = "text/plain";

static int port = 9999;

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

@Test
public void changeStateOnEachCallTest() throws IOException {
createWireMockStub(Scenario.STARTED, SECOND_STATE, TIP_01);
createWireMockStub(SECOND_STATE, THIRD_STATE, TIP_02);
createWireMockStub(THIRD_STATE, Scenario.STARTED, TIP_03);

}

private void createWireMockStub(String currentState, String nextState, String responseBody) {
stubFor(get(urlEqualTo("/java-tip"))
.inScenario("java tips")
.whenScenarioStateIs(currentState)
.willSetStateTo(nextState)
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", TEXT_PLAIN)
.withBody(responseBody)));
}

}

В приведенном выше классе мы используем класс правил WireMock JUnit WireMockRule . Это настраивает сервер WireMock при запуске теста JUnit.

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

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

  • whenScenarioStateIs : определяет, в каком состоянии должен находиться сценарий, чтобы WireMock мог использовать эту заглушку.
  • willSetStateTo : дает значение, которое WireMock устанавливает для состояния после того, как эта заглушка была использована.

Начальное состояние любого сценария — Scenario.STARTED . Итак, мы создаем заглушку, которая используется, когда состояние Scenario.STARTED. Это переводит состояние в SECOND_STATE.

Мы также добавляем заглушки для перехода из SECOND_STATE в THIRD_STATE и, наконец, из THIRD_STATE обратно в Scenario.STARTED. Итак, если мы продолжим вызывать конечную точку /java-tip , состояние изменится следующим образом:

Сценарий.STARTED -> SECOND_STATE -> THIRD_STATE -> Scenario.STARTED

5. Использование сценария

Чтобы использовать сценарий WireMock, мы просто делаем повторные вызовы конечной точки /java-tip . Итак, нам нужно изменить наш тестовый класс следующим образом:

@Test
public void changeStateOnEachCallTest() throws IOException {
createWireMockStub(Scenario.STARTED, SECOND_STATE, TIP_01);
createWireMockStub(SECOND_STATE, THIRD_STATE, TIP_02);
createWireMockStub(THIRD_STATE, Scenario.STARTED, TIP_03);

assertEquals(TIP_01, nextTip());
assertEquals(TIP_02, nextTip());
assertEquals(TIP_03, nextTip());
assertEquals(TIP_01, nextTip());
}

private String nextTip() throws ClientProtocolException, IOException {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet request = new HttpGet(String.format("http://localhost:%s/java-tip", port));
HttpResponse httpResponse = httpClient.execute(request);
return firstLineOfResponse(httpResponse);
}

private static String firstLineOfResponse(HttpResponse httpResponse) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(httpResponse.getEntity().getContent()))) {
return reader.readLine();
}
}

Метод nextTip() вызывает конечную точку /java-tip и затем возвращает ответ в виде строки . Поэтому мы используем это в каждом вызове assertEquals() , чтобы убедиться, что вызовы действительно заставляют сценарий циклически перемещаться между различными состояниями.

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

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

Как всегда, весь код, используемый в этом руководстве, доступен на GitHub .