Webtestclient: Version 5.2.6.release
Webtestclient: Version 5.2.6.release
Version 5.2.6.RELEASE
WebTestClient is a thin shell around WebClient, using it to perform requests and
exposing a dedicated, fluent API for verifying responses. WebTestClient binds to
a WebFlux application by using a mock request and response, or it can test any
web server over an HTTP connection.
1
Chapter 1. Setup
To create a WebTestClient you must choose one of several server setup options. Effectively you’re
either configuring the WebFlux application to bind to or using a URL to connect to a running
server.
Java
Kotlin
client = WebTestClient.bindToController(TestController()).build()
The preceding example loads the WebFlux Java configuration and registers the given controller.
The resulting WebFlux application is tested without an HTTP server by using mock request and
response objects. There are more methods on the builder to customize the default WebFlux Java
configuration.
Java
Kotlin
2
Java
@SpringJUnitConfig(WebConfig.class) ①
class MyTests {
WebTestClient client;
@BeforeEach
void setUp(ApplicationContext context) { ②
client = WebTestClient.bindToApplicationContext(context).build(); ③
}
}
Kotlin
@SpringJUnitConfig(WebConfig::class) ①
class MyTests {
@BeforeEach
fun setUp(context: ApplicationContext) { ②
client = WebTestClient.bindToApplicationContext(context).build() ③
}
}
Java
client = WebTestClient.bindToServer().baseUrl("http://localhost:8080").build();
3
Kotlin
client = WebTestClient.bindToServer().baseUrl("http://localhost:8080").build()
Java
Kotlin
client = WebTestClient.bindToController(TestController())
.configureClient()
.baseUrl("/test")
.build()
4
Chapter 2. Writing Tests
WebTestClient provides an API identical to WebClient up to the point of performing a request by
using exchange(). What follows after exchange() is a chained API workflow to verify responses.
Typically, you start by asserting the response status and headers, as follows:
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)
Then you specify how to decode and consume the response body:
Then you can use built-in assertions for the body. The following example shows one way to do so:
Java
client.get().uri("/persons")
.exchange()
.expectStatus().isOk()
.expectBodyList(Person.class).hasSize(3).contains(person);
Kotlin
import org.springframework.test.web.reactive.server.expectBodyList
client.get().uri("/persons")
.exchange()
.expectStatus().isOk()
.expectBodyList<Person>().hasSize(3).contains(person)
5
You can also go beyond the built-in assertions and create your own, as the following example
shows:
Java
import org.springframework.test.web.reactive.server.expectBody
client.get().uri("/persons/1")
.exchange()
.expectStatus().isOk()
.expectBody(Person.class)
.consumeWith(result -> {
// custom assertions (e.g. AssertJ)...
});
Kotlin
client.get().uri("/persons/1")
.exchange()
.expectStatus().isOk()
.expectBody<Person>()
.consumeWith {
// custom assertions (e.g. AssertJ)...
}
You can also exit the workflow and get a result, as follows:
Java
Kotlin
import org.springframework.test.web.reactive.server.expectBody
When you need to decode to a target type with generics, look for the overloaded
methods that accept ParameterizedTypeReference instead of Class<T>.
6
2.1. No Content
If the response has no content (or you do not care if it does) use Void.class, which ensures that
resources are released. The following example shows how to do so:
Java
client.get().uri("/persons/123")
.exchange()
.expectStatus().isNotFound()
.expectBody(Void.class);
Kotlin
client.get().uri("/persons/123")
.exchange()
.expectStatus().isNotFound
.expectBody<Unit>()
Alternatively, if you want to assert there is no response content, you can use code similar to the
following:
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()
7
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\"}")
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")
8
Java
Kotlin
import org.springframework.test.web.reactive.server.returnResult
Now you can consume the Flux<T>, assert decoded objects as they come, and then cancel at some
point when test objectives are met. We recommend using the StepVerifier from the reactor-test
module to do that, as the following example shows:
Java
StepVerifier.create(eventFlux)
.expectNext(person)
.expectNextCount(4)
.consumeNextWith(p -> ...)
.thenCancel()
.verify();
Kotlin
StepVerifier.create(eventFlux)
.expectNext(person)
.expectNextCount(4)
.consumeNextWith { p -> ... }
.thenCancel()
.verify()
9
examples on how to prepare a request with a body, including submitting form data, multipart
requests, and more.
10