Gymterview
middle

Как использовать WebTestClient для тестирования реактивных и обычных приложений?

WebTestClient — клиент для тестирования веб-приложений, поддерживающий как реактивные (WebFlux), так и классические (MVC) приложения. Предоставляет fluent API для выполнения запросов и проверки ответов.

С SpringBootTest (реальный сервер)

Пример кода
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class UserControllerWebClientTest {

    @Autowired
    private WebTestClient webTestClient;

    @Test
    void shouldGetAllUsers() {
        webTestClient.get()
            .uri("/api/users")
            .accept(MediaType.APPLICATION_JSON)
            .exchange()
            .expectStatus().isOk()
            .expectBodyList(UserDto.class)
            .hasSize(3)
            .contains(new UserDto(1L, "Иван"));
    }

    @Test
    void shouldCreateUser() {
        UserDto newUser = new UserDto(null, "Пётр");

        webTestClient.post()
            .uri("/api/users")
            .contentType(MediaType.APPLICATION_JSON)
            .bodyValue(newUser)
            .exchange()
            .expectStatus().isCreated()
            .expectBody(UserDto.class)
            .value(user -> {
                assertNotNull(user.getId());
                assertEquals("Пётр", user.getName());
            });
    }

    @Test
    void shouldReturnNotFound() {
        webTestClient.get()
            .uri("/api/users/999")
            .exchange()
            .expectStatus().isNotFound();
    }
}

Работа с JSON-телом ответа

Пример
@Test
void shouldVerifyResponseBody() {
    webTestClient.get()
        .uri("/api/users/1")
        .exchange()
        .expectStatus().isOk()
        .expectBody()
        .jsonPath("$.name").isEqualTo("Иван")
        .jsonPath("$.email").isNotEmpty()
        .jsonPath("$.id").isNumber();
}

С заголовками и аутентификацией

Пример
@Test
void shouldSendHeaders() {
    webTestClient.get()
        .uri("/api/protected")
        .header("Authorization", "Bearer jwt-token-here")
        .exchange()
        .expectStatus().isOk()
        .expectHeader().contentType(MediaType.APPLICATION_JSON)
        .expectHeader().exists("X-Custom-Header");
}

На собеседовании: интервьюер хочет услышать, что WebTestClient работает и с MVC, и с WebFlux, в отличие от MockMvc (только MVC) и TestRestTemplate (только реальный сервер). Частая ошибка — думать, что WebTestClient только для реактивных приложений.