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

Мокинг WebClient весной

Мокинг свободно Весна WebClient интерфейс для тестирования возможно, но тяжелая работа. MockWebServer является простой в использовании альтернативой.

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

1. Обзор

В эти дни мы ожидаем позвонить в API REST в большинстве наших сервисов. Весна предоставляет несколько вариантов для создания клиента REST, и WebClient рекомендуется .

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

2. Мокинг

У нас есть два основных варианта для насмешек в наших тестах:

  • Используйте Мокито имитировать поведение WebClient
  • Используйте WebClient по-настоящему, но издеваться над услугой, которая она вызывает, используя MockWebСервер (окхттп) Я не против.

3. Использование Мокито

Mockito является наиболее распространенной библиотекой насмешек для Java. Это хорошо обеспечивает заранее определенные ответы на вызовы методов, но все становится сложным, когда насмешки свободно API. Это связано с тем, что в свободном API много объектов проходит между кодом вызова и макетом.

Например, давайте проявим Служба обслуживания класс с getEmployeeById метод получения данных через HTTP с помощью WebClient :

public class EmployeeService {

    public EmployeeService(String baseUrl) {
        this.webClient = WebClient.create(baseUrl);
    }
    public Mono getEmployeeById(Integer employeeId) {
        return webClient
                .get()
                .uri("http://localhost:8080/employee/{id}", employeeId)
                .retrieve()
                .bodyToMono(Employee.class);
    }
}

Мы можем использовать Mockito, чтобы издеваться над этим:

@ExtendWith(MockitoExtension.class)
public class EmployeeServiceTest {
   
    @Test
    void givenEmployeeId_whenGetEmployeeById_thenReturnEmployee() {

        Integer employeeId = 100;
        Employee mockEmployee = new Employee(100, "Adam", "Sandler", 
          32, Role.LEAD_ENGINEER);
        when(webClientMock.get())
          .thenReturn(requestHeadersUriSpecMock);
        when(requestHeadersUriMock.uri("/employee/{id}", employeeId))
          .thenReturn(requestHeadersSpecMock);
        when(requestHeadersMock.retrieve())
          .thenReturn(responseSpecMock);
        when(responseMock.bodyToMono(Employee.class))
          .thenReturn(Mono.just(mockEmployee));

        Mono employeeMono = employeeService.getEmployeeById(employeeId);

        StepVerifier.create(employeeMono)
          .expectNextMatches(employee -> employee.getRole()
            .equals(Role.LEAD_ENGINEER))
          .verifyComplete();
    }

}

Как мы видим, мы должны предоставить различные макет объекта для каждого вызова в цепи, с четырьмя различными когда / затемРетурн требуется вызов. Это многословный и громоздкий . Это также требует от нас знать детали реализации того, как именно наш сервис использует WebClient, что делает это хрупкий способ тестирования.

Как мы можем написать лучшие тесты для WebClient?

4. Использование MockWebServer

MockWebСервер , построенный командой Square, это небольшой веб-сервер, который может принимать и отвечать на запросы HTTP.

Взаимодействие с MockWebСервер из наших тестовых случаев позволяет нашему коду использовать реальные вызовы HTTP в местную конечную точку . Мы получаем преимущество тестирования предполагаемых взаимодействий HTTP и ни одна из проблем насмешливый сложный беглый клиент.

Использование MockWebСервер это рекомендовано Весенней командой для написания интеграционных тестов .

4.1. Зависимости MockWebServer

Использовать MockWebСервер , мы должны добавить Maven зависимостей для обеих okhttp и mockwebserver к нашему пом.xml:


    com.squareup.okhttp3
    okhttp
    4.0.1
    test


    com.squareup.okhttp3
    mockwebserver
    4.0.1
    test

4.2. Добавление MockWebServer в наш тест

Давайте проверят наши Служба обслуживания с MockWebСервер :

public class EmployeeServiceMockWebServerTest {

    public static MockWebServer mockBackEnd;

    @BeforeAll
    static void setUp() throws IOException {
        mockBackEnd = new MockWebServer();
        mockBackEnd.start();
    }

    @AfterAll
    static void tearDown() throws IOException {
        mockBackEnd.shutdown();
    }
}

В вышеупомянутом тестовом классе JUnit setUp и tearDown метод заботится о создании и закрытии MockWebServer.

Следующим шагом является карта порта фактического вызова службы REST в MockWebServer’s портовые .

@BeforeEach
void initialize() {
    String baseUrl = String.format("http://localhost:%s", 
      mockBackEnd.getPort());
    employeeService = new EmployeeService(baseUrl);
}

Теперь пришло время создать заглушку так, чтобы MockWebСервер может ответить на HttpRequest .

4.3. Заглушая ответ

Давайте использовать MockWebServer’s удобный завеча метод очереди тестового ответа на веб-сервере:

@Test
void getEmployeeById() throws Exception {
    Employee mockEmployee = new Employee(100, "Adam", "Sandler", 
      32, Role.LEAD_ENGINEER);
    mockBackEnd.enqueue(new MockResponse()
      .setBody(objectMapper.writeValueAsString(mockEmployee))
      .addHeader("Content-Type", "application/json"));

    Mono employeeMono = employeeService.getEmployeeById(100);

    StepVerifier.create(employeeMono)
      .expectNextMatches(employee -> employee.getRole()
        .equals(Role.LEAD_ENGINEER))
      .verifyComplete();
}

Когда фактический вызов API будет из getEmployeeById (сотрудник IntegerId) метод в нашем Служба обслуживания класс, MockWebСервер будет отвечать с очередью заглушки .

4.4. Проверка запроса

Мы также можем захотеть убедиться, что MockWebСервер был отправлен правильный HttpRequest .

MockWebСервер имеет удобный метод, названный takeRequest который возвращает экземпляр ЗаписьРеквест :

RecordedRequest recordedRequest = mockBackEnd.takeRequest();
 
assertEquals("GET", recordedRequest.getMethod());
assertEquals("/employee/100", recordedRequest.getPath());

С ЗаписьРеквест , мы можем проверить HttpRequest , который был получен, чтобы убедиться, что наши WebClient послал его правильно .

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

В этом учебнике мы попробовали два основных варианта, доступных для макет WebClient на основе кода клиента REST .

Хотя Mockito работал и, возможно, хороший вариант для простых примеров, рекомендуемый подход заключается в использовании MockWebСервер .

Как всегда, исходный код для этой статьи доступен более чем на GitHub.