WebTestClient proporciona una API idéntica a WebClient, hasta la ejecución de la solicitud con usando exchange(). Para ver ejemplos de cómo preparar una solicitud con cualquier contenido, incluidos datos de formulario, datos de varias partes y más, consulte la documentación de WebClient.

Después de llamar a exchange(), WebTestClient diverge de WebClient y en su lugar continúa la respuesta. Flujo de trabajo de validación.

Para confirmar el estado de la respuesta y los encabezados, utilice lo siguiente:

Java

client.get().uri("/persons/1")
    .accept(MediaType.APPLICATION_JSON)
    .exchange()
    .expectStatus().isOk()
    .expectHeader().contentType(MediaType.APPLICATION_JSON);
Kotlin

client.get().uri("/persons/1")
    .accept(MediaType.APPLICATION_JSON)
    .exchange()
    .expectStatus().isOk()
    .expectHeader().contentType(MediaType.APPLICATION_JSON)

Si desea que se reconozcan todos los eventos esperados, incluso si uno de ellos falla, puede utilice expectAll(..) en lugar de varias llamadas consecutivas a expect*(..). Esta característica es similar a la compatibilidad con aserciones suaves en AssertJ y assertAll() en JUnit Jupiter.

Java

client.get().uri("/persons/1")
    .accept(MediaType.APPLICATION_JSON)
    .exchange()
    .expectAll(
        spec -> spec.expectStatus().isOk(),
        spec -> spec.expectHeader().contentType(MediaType.APPLICATION_JSON)
    );

Luego puede optar por decodificar el cuerpo de la respuesta utilizando uno de los siguientes métodos:

  • expectBody(Class<T>): Decodificación en un objeto.

  • expectBodyList(Class<T>): Decodificar y recopilar objetos en List<T>.

  • expectBody(): Decodificación en byte[] para contenido JSON o un contenido vacío body.

Y ejecute aserciones en los objetos de nivel superior resultantes:

Java
 
client.get().uri("/persons")
        .exchange()
        .expectStatus().isOk()
        .expectBodyList(Person.class).hasSize(3).contains(person);
Si necesita decodificar al tipo de destino
Kotlin

import org.springframework.test.web.reactive.server.expectBodyList
client.get().uri("/persons")
        .exchange()
        .expectStatus().isOk()
        .expectBodyList<Person>().hasSize(3).contains(person)

If las aserciones integradas no son suficientes, puede usarlas en su lugar este objeto y ejecutar cualquier otra declaración:

Java

import org.springframework.test.web.reactive.server.expectBody
client.get().uri("/persons/1")
        .exchange()
        .expectStatus().isOk()
        .expectBody(Person.class)
        .consumeWith(result -> {
            // special statements (eg AssertJ)...
        });
Kotlin

client.get().uri("/persons/1")
        .exchange()
        .expectStatus().isOk()
        .expectBody<Person>()
        .consumeWith {
            // special statements (eg AssertJ)...
        }

O puede salir del flujo de trabajo y obtener EntityExchangeResult:

Java
  
EntityExchangeResult<Person> result = client.get().uri("/persons/1")
        .exchange()
        .expectStatus().isOk()
        .expectBody(Person.class)
        .returnResult();
Kotlin

import org.springframework.test.web.reactive.server.expectBody
val result = client.get().uri("/persons/1")
        .exchange()
        .expectStatus().isOk
        .expectBody<Person>()
        .returnResult()
Si necesita decodificar al tipo de destino usando genéricos, busque métodos sobrecargados que acepten ParameterizedTypeReference en lugar de Clase<T>.

Sin contenido

Si se espera que la respuesta no tenga contenido, puede confirmarlo de la siguiente manera:

Java
 
client.post().uri("/persons")
        .body(personMono, Person.class)
        .exchange()
        .expectStatus().isCreated()
        .expectBody().isEmpty(); 
Kotlin

client.post().uri("/persons")
        .bodyValue(person)
        .exchange()
        .expectStatus().isCreated()
        .expectBody().isEmpty()

Si desea ignorar el contenido de la respuesta, a continuación se muestra el comunicado del contenido sin aserciones:

Java

client.get().uri("/persons/123")
        .exchange()
        .expectStatus().isNotFound()
        .expectBody(Void.class);
        
Kotlin
client.get().uri("/persons/123")
        .exchange()
        .expectStatus().isNotFound
        .expectBody<Unit>()

Contenido JSON

Puedes usar expectBody() sin un tipo de destino para hacer afirmaciones sobre contenido sin formato, en lugar de tener que hacerlo a través de objetos de nivel superior.

Para examinar el contenido JSON completo usando JSONAssert:

Java

client.get().uri("/persons/1")
        .exchange()
        .expectStatus().isOk()
        .expectBody()
        .json("{\"name\":\"Jane\"}") 
Kotlin

client.get().uri("/persons/1")
        .exchange()
        .expectStatus().isOk()
        .expectBody()
        .json("{\"name\":\"Jane\"}")

Para verificar el contenido JSON usando JSONPath:

Java

client.get().uri("/persons")
        .exchange()
        .expectStatus().isOk()
        .expectBody()
        .jsonPath("$[0].name").isEqualTo("Jane")
        .jsonPath("$[1].name").isEqualTo("Jason");
Kotlin
client.get().uri("/persons")
        .exchange()
        .expectStatus().isOk()
        .expectBody()
        .jsonPath("$[0].name").isEqualTo("Jane")
        .jsonPath("$[1].name").isEqualTo("Jason")

Transmitir respuestas

Para comprobar secuencias potencialmente infinitas, como "text/event-stream" o "application/x-ndjson", comience comprobando la respuesta estado y encabezados, y luego obtenga FluxExchangeResult:

Java
FluxExchangeResult<MyEvent> result = client.get().uri("/events")
        .accept(TEXT_EVENT_STREAM)
        .exchange()
        .expectStatus().isOk()
        .returnResult(MyEvent.class);
Kotlin
import org.springframework.test.web.reactive.server.returnResult
val result = client.get().uri("/events")
        .accept(TEXT_EVENT_STREAM)
        .exchange()
        .expectStatus().isOk()
        .returnResult<MyEvent>()

Ahora está listo para consumir el flujo de respuesta usando StepVerifier de reactor-test:

Java

Flux<Event> eventFlux = result.getResponseBody();
StepVerifier.create(eventFlux)
        .expectNext(person)
        .expectNextCount(4)
        .consumeNextWith(p -> ...)
        .thenCancel()
        .verify();
Kotlin

val eventFlux = result.getResponseBody()
StepVerifier.create(eventFlux)
        .expectNext(person)
        .expectNextCount(4)
        .consumeNextWith { p -> ... }
        .thenCancel()
        .verify()

Aserciones de MockMvc

WebTestClient es HTTP cliente, por lo que solo puede verificar lo que hay en la respuesta del cliente, incluido el estado, los encabezados y el cuerpo.

Al probar una aplicación Spring MVC con una configuración de servidor MockMvc, tiene la capacidad adicional de realizar más afirmaciones en la respuesta del servidor. Para hacer esto, comience obteniendo el ExchangeResult después de agregar la afirmación al cuerpo:

Java

// Para una respuesta con cuerpo
EntityExchangeResult<Person> result = client.get().uri("/persons/1")
        .exchange()
        .expectStatus().isOk()
        .expectBody(Person.class)
        .returnResult();
// Para una respuesta sin cuerpo
EntityExchangeResult<Void> result = client.get().uri("/path")
        .exchange()
        .expectBody().isEmpty();
Kotlin

// Para una respuesta con un cuerpo
val result = client.get().uri("/persons/1")
        .exchange()
        .expectStatus().isOk()
        .expectBody(Person.class)
        .returnResult();
// Para una respuesta sin valor de cuerpo
val result = client.get().uri("/path")
        .exchange()
        .expectBody().isEmpty();;

Luego cambie a las afirmaciones de respuesta del servidor MockMvc:

Java

MockMvcWebTestClient.resultActionsFor(result)
        .andExpect(model().attribute("integer", 3))
        .andExpect(model().attribute("string", "a string value"))
Kotlin
            MockMvcWebTestClient.resultActionsFor(result)
        .andExpect(model().attribute("integer", 3))
        .andExpect(model().attribute("string", "a string value"));