Статьи

Интегрируйте Wiremock в Java-приложение Spring Boot для проверки внешних зависимостей

Вступление

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

Добавить зависимость от Wiremock

Сначала вы захотите добавить зависимость Wiremock. Вы можете скачать обычную зависимость или полную версию JAR, которая содержит все ее зависимости. Мы будем использовать стандартную зависимость здесь. Добавьте следующую зависимость в ваш build.gradle

build.gradle

1
2
3
dependencies {
    testCompile('com.github.tomakehurst:wiremock:2.1.12')
}

Добавить модульный тест Wiremock

Вот полный модульный тест, который вы можете использовать для тестирования вашей интеграции с Wiremock. Этот модульный тест использует правило jUnit4 для вращения сервера Wiremock на порту 8089 и его выключения после каждого теста. Мы используем метод stubFor, чтобы определить ложную конечную точку и ответ. Мы используем Spring RestTemplate для создания HTTP-запроса на наш фиктивный сервер и захвата результата.

WiremockTests.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class WiremockTests {
 
    RestTemplate restTemplate;
    ResponseEntity response;
 
    @Rule
    public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().port(8089).httpsPort(8443));
 
    @Before
    public void setup() throws Exception {
        restTemplate = new RestTemplate();
        response = null;
    }
 
    @Test
    public void givenWireMockAdminEndpoint_whenGetWithoutParams_thenVerifyRequest() {
 
        RestTemplate restTemplate = new RestTemplate();
 
        response = restTemplate.getForEntity("http://localhost:8089/__admin", String.class);
 
        assertThat("Verify Response Body", response.getBody().contains("mappings"));
        assertThat("Verify Status Code", response.getStatusCode().equals(HttpStatus.OK));
    }
 
    @Test
    public void givenWireMockEndpoint_whenGetWithoutParams_thenVerifyRequest() {
        stubFor(get(urlEqualTo("/api/resource/"))
                .willReturn(aResponse()
                        .withStatus(HttpStatus.OK.value())
                        .withHeader("Content-Type", TEXT_PLAIN_VALUE)
                        .withBody("test")));
 
        response = restTemplate.getForEntity("http://localhost:8089/api/resource/", String.class);
 
        assertThat("Verify Response Body", response.getBody().contains("test"));
        assertThat("Verify Status Code", response.getStatusCode().equals(HttpStatus.OK));
 
        verify(getRequestedFor(urlMatching("/api/resource/.*")));
    }
}

Вы можете запустить этот тест, и, если он завершен, вы успешно интегрировали Wiremock в свое приложение.

Детализируйте в модульном тесте

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

WiremockTests.java

1
2
3
4
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.springframework.http.MediaType.TEXT_PLAIN_VALUE;

Правило jUnit4

Этот jUnit4 @rule будет автоматически управлять жизненным циклом сервера Wiremock, а также запускать и выключать Wiremock для каждого теста. Вы также сможете реализовать это с помощью метода setup () и teardown (), но правило jUnit4 будет более четким и лаконичным.

WiremockTests.java

1
2
@Rule
    public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().port(8089).httpsPort(8443));

Оконечная точка и ответ

В этом коде используется метод stubFor (), который был статически импортирован для определения конечной точки, / api / resource / и «теста» тела ответа в виде простого текста. Вы также можете вернуть ответ JSON или XML, используя этот метод, изменив Content- Тип и ответ тела

WiremockTests.java

1
2
3
4
5
stubFor(get(urlEqualTo("/api/resource/"))
                .willReturn(aResponse()
                        .withStatus(HttpStatus.OK.value())
                        .withHeader("Content-Type", TEXT_PLAIN_VALUE)
                        .withBody("test")));

Spring RestTemplate

Мы используем класс Spring RestTemplate для выполнения HTTP-запроса GET по адресу http: // localhost: 8089 / api / resource /, попадающего на заглушенную конечную точку сервера wiremock. В этом случае мы ожидаем ответа сущности String.class, потому что это то, что мы определили в методе stubFor () . Вам нужно будет определить объект POJO для захвата ответа JSON от вашего метода заглушки, если это то, что вы настроили. Мы фиксируем ответ в объекте ResponseEntity, который фиксирует тело ответа, заголовки и код состояния, а также другую информацию о запросе.

WiremockTests.java

1
response = restTemplate.getForEntity("http://localhost:8089/api/resource/", String.class);

Запуск и остановка сервера Wiremock вручную

Вы можете запускать и останавливать сервер Wiremock вручную, не используя правило jUnit4 для управления жизненным циклом. Вы можете захотеть сделать это методом начальной загрузки, когда ваше приложение запускается.

ServiceClass.java

1
2
3
4
5
6
WireMockServer wireMockServer = new WireMockServer(wireMockConfig().port(8089)); //No-args constructor will start on port 8080, no HTTPS
wireMockServer.start();
 
WireMock.reset();
 
wireMockServer.stop();

Вывод

Теперь у вас есть настройка Wiremock в вашем проекте. Вы можете использовать Wiremock в модульных и интеграционных тестах, чтобы заглушить внешние зависимости, а также ускорить разработку в вашей локальной среде. Вы можете прочитать больше о настройке Wiremock здесь: http://wiremock.org/docs/getting-started/