Skip to content

Commit 02e928e

Browse files
committed
Docs for the WebTestClient AssertJ integration
Closes gh-35737
1 parent 7445f54 commit 02e928e

File tree

2 files changed

+108
-9
lines changed

2 files changed

+108
-9
lines changed

framework-docs/modules/ROOT/pages/testing/webtestclient.adoc

Lines changed: 97 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -270,16 +270,26 @@ Kotlin::
270270
======
271271

272272

273+
274+
273275
[[webtestclient-tests]]
274276
== Writing Tests
275277

276-
`WebTestClient` provides an API identical to xref:web/webflux-webclient.adoc[WebClient]
277-
up to the point of performing a request by using `exchange()`. See the
278-
xref:web/webflux-webclient/client-body.adoc[WebClient] documentation for examples on how to
279-
prepare a request with any content including form data, multipart data, and more.
278+
xref:web/webflux-webclient.adoc[WebClient] and `WebTestClient` have
279+
the same API up to the point of the call to `exchange()`. After that, `WebTestClient`
280+
provides two alternative ways to verify the response:
281+
282+
1. xref:webtestclient-workflow[Built-in Assertions] extend the request workflow with a chain of expectations
283+
2. xref:webtestclient-assertj[AssertJ Integration] to verify the response via `assertThat()` statements
284+
285+
TIP: See the xref:web/webflux-webclient/client-body.adoc[WebClient] documentation for
286+
examples on how to prepare a request with any content including form data,
287+
multipart data, and more.
280288

281-
After the call to `exchange()`, `WebTestClient` diverges from the `WebClient` and
282-
instead continues with a workflow to verify responses.
289+
290+
291+
[[webtestclient-workflow]]
292+
=== Built-in Assertions
283293

284294
To assert the response status and headers, use the following:
285295

@@ -443,8 +453,10 @@ that accept
443453
{spring-framework-api}/core/ParameterizedTypeReference.html[`ParameterizedTypeReference`]
444454
instead of `Class<T>`.
445455

456+
457+
446458
[[webtestclient-no-content]]
447-
=== No Content
459+
==== No Content
448460

449461
If the response is not expected to have content, you can assert that as follows:
450462

@@ -499,8 +511,10 @@ Kotlin::
499511
----
500512
======
501513

514+
515+
502516
[[webtestclient-json]]
503-
=== JSON Content
517+
==== JSON Content
504518

505519
You can use `expectBody()` without a target type to perform assertions on the raw
506520
content rather than through higher level Object(s).
@@ -561,8 +575,10 @@ Kotlin::
561575
----
562576
======
563577

578+
579+
564580
[[webtestclient-stream]]
565-
=== Streaming Responses
581+
==== Streaming Responses
566582

567583
To test potentially infinite streams such as `"text/event-stream"` or
568584
`"application/x-ndjson"`, start by verifying the response status and headers, and then
@@ -629,6 +645,78 @@ Kotlin::
629645
----
630646
======
631647

648+
649+
650+
[[webtestclient-assertj]]
651+
=== AssertJ Integration
652+
653+
`WebTestClientResponse` is the main entry point for the AssertJ integration.
654+
It is an `AssertProvider` that wraps the `ResponseSpec` of an exchange in order to enable
655+
use of `assertThat()` statements. For example:
656+
657+
[tabs]
658+
======
659+
Java::
660+
+
661+
[source,java,indent=0,subs="verbatim,quotes"]
662+
----
663+
ResponseSpec spec = client.get().uri("/persons").exchange();
664+
665+
WebTestClientResponse response = WebTestClientResponse.from(spec);
666+
assertThat(response).hasStatusOk();
667+
assertThat(response).hasContentTypeCompatibleWith(MediaType.TEXT_PLAIN);
668+
// ...
669+
----
670+
671+
Kotlin::
672+
+
673+
[source,kotlin,indent=0,subs="verbatim,quotes"]
674+
----
675+
val spec = client.get().uri("/persons").exchange()
676+
677+
val response = WebTestClientResponse.from(spec)
678+
assertThat(response).hasStatusOk()
679+
assertThat(response).hasContentTypeCompatibleWith(MediaType.TEXT_PLAIN)
680+
// ...
681+
----
682+
======
683+
684+
You can also use the built-in workflow first, and then obtain an `ExchangeResult` to wrap
685+
and continue with AssertJ. For example:
686+
687+
[tabs]
688+
======
689+
Java::
690+
+
691+
[source,java,indent=0,subs="verbatim,quotes"]
692+
----
693+
ExchangeResult result = client.get().uri("/persons").exchange()
694+
. // ...
695+
.returnResult();
696+
697+
WebTestClientResponse response = WebTestClientResponse.from(result);
698+
assertThat(response).hasStatusOk();
699+
assertThat(response).hasContentTypeCompatibleWith(MediaType.TEXT_PLAIN);
700+
// ...
701+
----
702+
703+
Kotlin::
704+
+
705+
[source,kotlin,indent=0,subs="verbatim,quotes"]
706+
----
707+
val result = client.get().uri("/persons").exchange()
708+
. // ...
709+
.returnResult()
710+
711+
val response = WebTestClientResponse.from(spec)
712+
assertThat(response).hasStatusOk()
713+
assertThat(response).hasContentTypeCompatibleWith(MediaType.TEXT_PLAIN)
714+
// ...
715+
----
716+
======
717+
718+
719+
632720
[[webtestclient-mockmvc]]
633721
=== MockMvc Assertions
634722

spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,17 @@ interface ResponseSpec {
914914
*/
915915
BodyContentSpec expectBody();
916916

917+
/**
918+
* Return an {@link ExchangeResult} with the raw content. Effectively, a shortcut for:
919+
* <pre class="code">
920+
* .returnResult(byte[].class)
921+
* </pre>
922+
* @since 7.0
923+
*/
924+
default ExchangeResult returnResult() {
925+
return returnResult(byte[].class);
926+
}
927+
917928
/**
918929
* Exit the chained flow in order to consume the response body externally,
919930
* for example, via {@link reactor.test.StepVerifier}.

0 commit comments

Comments
 (0)