WebTestClient
предоставляет API-интерфейс, идентичный WebClient, вплоть до выполнения запроса с помощью exchange()
. Примеры подготовки запроса с любым содержимым, включая данные формы, многокомпонентные данные и многое другое, см. в документации по WebClient.
После вызова exchange()
WebTestClient
расходится с WebClient
и вместо этого продолжает рабочий процесс проверки достоверности ответов.
Чтобы подтвердить статус ответа и заголовки, используйте следующее:
client.get().uri("/persons/1")
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus().isOk()
.expectHeader().contentType(MediaType.APPLICATION_JSON);
client.get().uri("/persons/1")
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus().isOk()
.expectHeader().contentType(MediaType.APPLICATION_JSON)
Если нужно, чтобы все ожидаемые события были подтверждены, даже если одно из них не сработало, то можно использовать expectAll(..)
вместо нескольких последовательных вызовов expect*(..)
. Эта функция похожа на поддержку мягких утверждений в AssertJ и assertAll()
в JUnit Jupiter.
client.get().uri("/persons/1")
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectAll(
spec -> spec.expectStatus().isOk(),
spec -> spec.expectHeader().contentType(MediaType.APPLICATION_JSON)
);
Затем можно выбрать декодирование тела ответа с помощью одного из следующих способов:
-
expectBody(Class<T>)
: Декодируем в один объект. -
expectBodyList(Class<T>)
: Декодируемым и собираем объекты вList<T>
. -
expectBody()
: Декодируем вbyte[]
для содержимого JSON или пустого тела.
И выполняем утверждения на результирующем объекте(ах) более высокого уровня:
client.get().uri("/persons")
.exchange()
.expectStatus().isOk()
.expectBodyList(Person.class).hasSize(3).contains(person);
import org.springframework.test.web.reactive.server.expectBodyList
client.get().uri("/persons")
.exchange()
.expectStatus().isOk()
.expectBodyList<Person>().hasSize(3).contains(person)
Если встроенных утверждений недостаточно, можно использовать вместо этого объект и выполнить любые другие утверждения:
import org.springframework.test.web.reactive.server.expectBody
client.get().uri("/persons/1")
.exchange()
.expectStatus().isOk()
.expectBody(Person.class)
.consumeWith(result -> {
// специальные утверждения (например, AssertJ)...
});
client.get().uri("/persons/1")
.exchange()
.expectStatus().isOk()
.expectBody<Person>()
.consumeWith {
// специальные утверждения (например, AssertJ)...
}
Или вы можете выйти из рабочего процесса и получить EntityExchangeResult
:
EntityExchangeResult<Person> result = client.get().uri("/persons/1")
.exchange()
.expectStatus().isOk()
.expectBody(Person.class)
.returnResult();
import org.springframework.test.web.reactive.server.expectBody
val result = client.get().uri("/persons/1")
.exchange()
.expectStatus().isOk
.expectBody<Person>()
.returnResult()
ParameterizedTypeReference
вместо Class<T>
.
Отсутствие содержимого
Если ожидается, что в ответе не будет содержимого, то вы можете подтвердить это следующим образом:
client.post().uri("/persons")
.body(personMono, Person.class)
.exchange()
.expectStatus().isCreated()
.expectBody().isEmpty();
client.post().uri("/persons")
.bodyValue(person)
.exchange()
.expectStatus().isCreated()
.expectBody().isEmpty()
Если нужно проигнорировать содержимое ответа, то ниже приведено высвобождение содержимого без каких-либо утверждений:
client.get().uri("/persons/123")
.exchange()
.expectStatus().isNotFound()
.expectBody(Void.class);
client.get().uri("/persons/123")
.exchange()
.expectStatus().isNotFound
.expectBody<Unit>()
Содержимое JSON
Можно использовать expectBody()
без целевого типа, чтобы выполнять утверждения для неформатированного содержимого, а не делать это через объект(ы) более высокого уровня.
Чтобы проверить полное содержимое JSON с помощью JSONAssert:
client.get().uri("/persons/1")
.exchange()
.expectStatus().isOk()
.expectBody()
.json("{\"name\":\"Jane\"}")
client.get().uri("/persons/1")
.exchange()
.expectStatus().isOk()
.expectBody()
.json("{\"name\":\"Jane\"}")
Чтобы проверить содержимое JSON с помощью JSONPath:
client.get().uri("/persons")
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("$[0].name").isEqualTo("Jane")
.jsonPath("$[1].name").isEqualTo("Jason");
client.get().uri("/persons")
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("$[0].name").isEqualTo("Jane")
.jsonPath("$[1].name").isEqualTo("Jason")
Потоковые ответы
Чтобы проверить потенциально бесконечные потоки, такие как "text/event-stream"
или "application/x-ndjson"
, начните с проверки статуса и заголовков ответа, а затем получите FluxExchangeResult
:
FluxExchangeResult<MyEvent> result = client.get().uri("/events")
.accept(TEXT_EVENT_STREAM)
.exchange()
.expectStatus().isOk()
.returnResult(MyEvent.class);
import org.springframework.test.web.reactive.server.returnResult
val result = client.get().uri("/events")
.accept(TEXT_EVENT_STREAM)
.exchange()
.expectStatus().isOk()
.returnResult<MyEvent>()
Теперь вы готовы потреблять поток ответов с помощью StepVerifier
из reactor-test
:
Flux<Event> eventFlux = result.getResponseBody();
StepVerifier.create(eventFlux)
.expectNext(person)
.expectNextCount(4)
.consumeNextWith(p -> ...)
.thenCancel()
.verify();
val eventFlux = result.getResponseBody()
StepVerifier.create(eventFlux)
.expectNext(person)
.expectNextCount(4)
.consumeNextWith { p -> ... }
.thenCancel()
.verify()
Утверждения MockMvc
WebTestClient
– это HTTP-клиент, поэтому он может проверять только то, что находится в ответе клиента, включая статус, заголовки и тело.
При тестировании приложения Spring MVC с настройкой сервера MockMvc вам доступна дополнительная возможность выполнять дальнейшие утверждения для ответа сервера. Для этого начните с получения ExchangeResult
после добавления утверждения к телу:
// Для ответа с телом
EntityExchangeResult<Person> result = client.get().uri("/persons/1")
.exchange()
.expectStatus().isOk()
.expectBody(Person.class)
.returnResult();
// Для ответа без тела
EntityExchangeResult<Void> result = client.get().uri("/path")
.exchange()
.expectBody().isEmpty();
// Для ответа с телом
val result = client.get().uri("/persons/1")
.exchange()
.expectStatus().isOk()
.expectBody(Person.class)
.returnResult();
// Для ответа без тела
val result = client.get().uri("/path")
.exchange()
.expectBody().isEmpty();
Затем переключитесь на утверждения ответа сервера MockMvc:
MockMvcWebTestClient.resultActionsFor(result)
.andExpect(model().attribute("integer", 3))
.andExpect(model().attribute("string", "a string value"));
MockMvcWebTestClient.resultActionsFor(result)
.andExpect(model().attribute("integer", 3))
.andExpect(model().attribute("string", "a string value"));
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ