|
|
|
@ -27,11 +27,16 @@ a URL to connect to a running server. |
|
|
|
|
|
|
|
|
|
|
|
The following example shows how to create a server setup to test one `@Controller` at a time: |
|
|
|
The following example shows how to create a server setup to test one `@Controller` at a time: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,intent=0] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
.Java |
|
|
|
---- |
|
|
|
---- |
|
|
|
client = WebTestClient.bindToController(new TestController()).build(); |
|
|
|
client = WebTestClient.bindToController(new TestController()).build(); |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
|
|
|
|
.Kotlin |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
client = WebTestClient.bindToController(TestController()).build() |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
The preceding example loads the <<web-reactive.adoc#webflux-config, WebFlux Java configuration>> |
|
|
|
The preceding example loads the <<web-reactive.adoc#webflux-config, WebFlux Java configuration>> |
|
|
|
and registers the given controller. The resulting WebFlux application is tested |
|
|
|
and registers the given controller. The resulting WebFlux application is tested |
|
|
|
@ -46,12 +51,18 @@ on the builder to customize the default WebFlux Java configuration. |
|
|
|
The following example shows how to set up a server from a |
|
|
|
The following example shows how to set up a server from a |
|
|
|
<<web-reactive.adoc#webflux-fn, RouterFunction>>: |
|
|
|
<<web-reactive.adoc#webflux-fn, RouterFunction>>: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,intent=0] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
.Java |
|
|
|
---- |
|
|
|
---- |
|
|
|
RouterFunction<?> route = ... |
|
|
|
RouterFunction<?> route = ... |
|
|
|
client = WebTestClient.bindToRouterFunction(route).build(); |
|
|
|
client = WebTestClient.bindToRouterFunction(route).build(); |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
|
|
|
|
.Kotlin |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
val route: RouterFunction<*> = ... |
|
|
|
|
|
|
|
val client = WebTestClient.bindToRouterFunction(route).build() |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
Internally, the configuration is passed to `RouterFunctions.toWebHandler`. |
|
|
|
Internally, the configuration is passed to `RouterFunctions.toWebHandler`. |
|
|
|
The resulting WebFlux application is tested without an HTTP server by using mock |
|
|
|
The resulting WebFlux application is tested without an HTTP server by using mock |
|
|
|
@ -65,11 +76,10 @@ request and response objects. |
|
|
|
The following example shows how to setup a server from the Spring configuration of your application or |
|
|
|
The following example shows how to setup a server from the Spring configuration of your application or |
|
|
|
some subset of it: |
|
|
|
some subset of it: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,intent=0] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
.Java |
|
|
|
---- |
|
|
|
---- |
|
|
|
@RunWith(SpringRunner.class) |
|
|
|
@SpringJUnitConfig(WebConfig.class) // <1> |
|
|
|
@ContextConfiguration(classes = WebConfig.class) // <1> |
|
|
|
|
|
|
|
public class MyTests { |
|
|
|
public class MyTests { |
|
|
|
|
|
|
|
|
|
|
|
@Autowired |
|
|
|
@Autowired |
|
|
|
@ -77,13 +87,33 @@ some subset of it: |
|
|
|
|
|
|
|
|
|
|
|
private WebTestClient client; |
|
|
|
private WebTestClient client; |
|
|
|
|
|
|
|
|
|
|
|
@Before |
|
|
|
@BeforeEach |
|
|
|
public void setUp() { |
|
|
|
public void setUp() { |
|
|
|
client = WebTestClient.bindToApplicationContext(context).build(); // <3> |
|
|
|
client = WebTestClient.bindToApplicationContext(context).build(); // <3> |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
<1> Specify the configuration to load |
|
|
|
|
|
|
|
<2> Inject the configuration |
|
|
|
|
|
|
|
<3> Create the `WebTestClient` |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
|
|
|
|
.Kotlin |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
@SpringJUnitConfig(WebConfig::class) // <1> |
|
|
|
|
|
|
|
class MyTests { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Autowired |
|
|
|
|
|
|
|
lateinit var context: ApplicationContext // <2> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lateinit var client: WebTestClient |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@BeforeEach |
|
|
|
|
|
|
|
fun setUp() { |
|
|
|
|
|
|
|
client = WebTestClient.bindToApplicationContext(context).build() // <3> |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
---- |
|
|
|
<1> Specify the configuration to load |
|
|
|
<1> Specify the configuration to load |
|
|
|
<2> Inject the configuration |
|
|
|
<2> Inject the configuration |
|
|
|
<3> Create the `WebTestClient` |
|
|
|
<3> Create the `WebTestClient` |
|
|
|
@ -100,11 +130,16 @@ using mock request and response objects. |
|
|
|
|
|
|
|
|
|
|
|
The following server setup option lets you connect to a running server: |
|
|
|
The following server setup option lets you connect to a running server: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,intent=0] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
.Java |
|
|
|
---- |
|
|
|
---- |
|
|
|
client = WebTestClient.bindToServer().baseUrl("http://localhost:8080").build(); |
|
|
|
client = WebTestClient.bindToServer().baseUrl("http://localhost:8080").build(); |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
|
|
|
|
.Kotlin |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
client = WebTestClient.bindToServer().baseUrl("http://localhost:8080").build() |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -116,14 +151,22 @@ options, including base URL, default headers, client filters, and others. These |
|
|
|
are readily available following `bindToServer`. For all others, you need to use |
|
|
|
are readily available following `bindToServer`. For all others, you need to use |
|
|
|
`configureClient()` to transition from server to client configuration, as follows: |
|
|
|
`configureClient()` to transition from server to client configuration, as follows: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,intent=0] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
.Java |
|
|
|
---- |
|
|
|
---- |
|
|
|
client = WebTestClient.bindToController(new TestController()) |
|
|
|
client = WebTestClient.bindToController(new TestController()) |
|
|
|
.configureClient() |
|
|
|
.configureClient() |
|
|
|
.baseUrl("/test") |
|
|
|
.baseUrl("/test") |
|
|
|
.build(); |
|
|
|
.build(); |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
|
|
|
|
.Kotlin |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
client = WebTestClient.bindToController(TestController()) |
|
|
|
|
|
|
|
.configureClient() |
|
|
|
|
|
|
|
.baseUrl("/test") |
|
|
|
|
|
|
|
.build() |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -137,15 +180,23 @@ up to the point of performing a request by using `exchange()`. What follows afte |
|
|
|
|
|
|
|
|
|
|
|
Typically, you start by asserting the response status and headers, as follows: |
|
|
|
Typically, you start by asserting the response status and headers, as follows: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,intent=0] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
.Java |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
client.get().uri("/persons/1") |
|
|
|
|
|
|
|
.accept(MediaType.APPLICATION_JSON) |
|
|
|
|
|
|
|
.exchange() |
|
|
|
|
|
|
|
.expectStatus().isOk() |
|
|
|
|
|
|
|
.expectHeader().contentType(MediaType.APPLICATION_JSON) |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
|
|
|
|
.Kotlin |
|
|
|
---- |
|
|
|
---- |
|
|
|
client.get().uri("/persons/1") |
|
|
|
client.get().uri("/persons/1") |
|
|
|
.accept(MediaType.APPLICATION_JSON) |
|
|
|
.accept(MediaType.APPLICATION_JSON) |
|
|
|
.exchange() |
|
|
|
.exchange() |
|
|
|
.expectStatus().isOk() |
|
|
|
.expectStatus().isOk() |
|
|
|
.expectHeader().contentType(MediaType.APPLICATION_JSON) |
|
|
|
.expectHeader().contentType(MediaType.APPLICATION_JSON) |
|
|
|
// ... |
|
|
|
|
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
Then you specify how to decode and consume the response body: |
|
|
|
Then you specify how to decode and consume the response body: |
|
|
|
@ -156,18 +207,32 @@ 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: |
|
|
|
Then you can use built-in assertions for the body. The following example shows one way to do so: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,intent=0] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
.Java |
|
|
|
---- |
|
|
|
---- |
|
|
|
client.get().uri("/persons") |
|
|
|
client.get().uri("/persons") |
|
|
|
.exchange() |
|
|
|
.exchange() |
|
|
|
.expectStatus().isOk() |
|
|
|
.expectStatus().isOk() |
|
|
|
.expectBodyList(Person.class).hasSize(3).contains(person); |
|
|
|
.expectBodyList(Person.class).hasSize(3).contains(person); |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
|
|
|
|
.Kotlin |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
import org.springframework.test.web.reactive.server.expectBodyList |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
client.get().uri("/persons") |
|
|
|
|
|
|
|
.exchange() |
|
|
|
|
|
|
|
.expectStatus().isOk() |
|
|
|
|
|
|
|
.expectBodyList<Person>().hasSize(3).contains(person) |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
You can also go beyond the built-in assertions and create your own, as the following example shows: |
|
|
|
You can also go beyond the built-in assertions and create your own, as the following example shows: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
|
|
|
|
.Java |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
import org.springframework.test.web.reactive.server.expectBody |
|
|
|
|
|
|
|
|
|
|
|
client.get().uri("/persons/1") |
|
|
|
client.get().uri("/persons/1") |
|
|
|
.exchange() |
|
|
|
.exchange() |
|
|
|
.expectStatus().isOk() |
|
|
|
.expectStatus().isOk() |
|
|
|
@ -176,9 +241,22 @@ You can also go beyond the built-in assertions and create your own, as the follo |
|
|
|
// custom assertions (e.g. AssertJ)... |
|
|
|
// custom assertions (e.g. AssertJ)... |
|
|
|
}); |
|
|
|
}); |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
|
|
|
|
.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: |
|
|
|
You can also exit the workflow and get a result, as follows: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
|
|
|
|
.Java |
|
|
|
---- |
|
|
|
---- |
|
|
|
EntityExchangeResult<Person> result = client.get().uri("/persons/1") |
|
|
|
EntityExchangeResult<Person> result = client.get().uri("/persons/1") |
|
|
|
.exchange() |
|
|
|
.exchange() |
|
|
|
@ -186,6 +264,17 @@ You can also exit the workflow and get a result, as follows: |
|
|
|
.expectBody(Person.class) |
|
|
|
.expectBody(Person.class) |
|
|
|
.returnResult(); |
|
|
|
.returnResult(); |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
|
|
|
|
.Kotlin |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
import org.springframework.test.web.reactive.server.expectBody |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val result = client.get().uri("/persons/1") |
|
|
|
|
|
|
|
.exchange() |
|
|
|
|
|
|
|
.expectStatus().isOk |
|
|
|
|
|
|
|
.expectBody<Person>() |
|
|
|
|
|
|
|
.returnResult() |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
TIP: When you need to decode to a target type with generics, look for the overloaded methods |
|
|
|
TIP: When you need to decode to a target type with generics, look for the overloaded methods |
|
|
|
that accept |
|
|
|
that accept |
|
|
|
@ -200,19 +289,27 @@ instead of `Class<T>`. |
|
|
|
If the response has no content (or you do not care if it does) use `Void.class`, which ensures |
|
|
|
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: |
|
|
|
that resources are released. The following example shows how to do so: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,intent=0] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
.Java |
|
|
|
---- |
|
|
|
---- |
|
|
|
client.get().uri("/persons/123") |
|
|
|
client.get().uri("/persons/123") |
|
|
|
.exchange() |
|
|
|
.exchange() |
|
|
|
.expectStatus().isNotFound() |
|
|
|
.expectStatus().isNotFound() |
|
|
|
.expectBody(Void.class); |
|
|
|
.expectBody(Void.class); |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
|
|
|
|
.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: |
|
|
|
Alternatively, if you want to assert there is no response content, you can use code similar to the following: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,intent=0] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
.Java |
|
|
|
---- |
|
|
|
---- |
|
|
|
client.post().uri("/persons") |
|
|
|
client.post().uri("/persons") |
|
|
|
.body(personMono, Person.class) |
|
|
|
.body(personMono, Person.class) |
|
|
|
@ -220,7 +317,15 @@ Alternatively, if you want to assert there is no response content, you can use c |
|
|
|
.expectStatus().isCreated() |
|
|
|
.expectStatus().isCreated() |
|
|
|
.expectBody().isEmpty(); |
|
|
|
.expectBody().isEmpty(); |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
|
|
|
|
.Kotlin |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
client.post().uri("/persons") |
|
|
|
|
|
|
|
.bodyValue(person) |
|
|
|
|
|
|
|
.exchange() |
|
|
|
|
|
|
|
.expectStatus().isCreated() |
|
|
|
|
|
|
|
.expectBody().isEmpty() |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[webtestclient-json]] |
|
|
|
[[webtestclient-json]] |
|
|
|
@ -230,8 +335,17 @@ When you use `expectBody()`, the response is consumed as a `byte[]`. This is use |
|
|
|
raw content assertions. For example, you can use |
|
|
|
raw content assertions. For example, you can use |
|
|
|
https://jsonassert.skyscreamer.org[JSONAssert] to verify JSON content, as follows: |
|
|
|
https://jsonassert.skyscreamer.org[JSONAssert] to verify JSON content, as follows: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,intent=0] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
.Java |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
client.get().uri("/persons/1") |
|
|
|
|
|
|
|
.exchange() |
|
|
|
|
|
|
|
.expectStatus().isOk() |
|
|
|
|
|
|
|
.expectBody() |
|
|
|
|
|
|
|
.json("{\"name\":\"Jane\"}") |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
|
|
|
|
.Kotlin |
|
|
|
---- |
|
|
|
---- |
|
|
|
client.get().uri("/persons/1") |
|
|
|
client.get().uri("/persons/1") |
|
|
|
.exchange() |
|
|
|
.exchange() |
|
|
|
@ -242,8 +356,8 @@ https://jsonassert.skyscreamer.org[JSONAssert] to verify JSON content, as follow |
|
|
|
|
|
|
|
|
|
|
|
You can also use https://github.com/jayway/JsonPath[JSONPath] expressions, as follows: |
|
|
|
You can also use https://github.com/jayway/JsonPath[JSONPath] expressions, as follows: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,intent=0] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
.Java |
|
|
|
---- |
|
|
|
---- |
|
|
|
client.get().uri("/persons") |
|
|
|
client.get().uri("/persons") |
|
|
|
.exchange() |
|
|
|
.exchange() |
|
|
|
@ -252,6 +366,16 @@ You can also use https://github.com/jayway/JsonPath[JSONPath] expressions, as fo |
|
|
|
.jsonPath("$[0].name").isEqualTo("Jane") |
|
|
|
.jsonPath("$[0].name").isEqualTo("Jane") |
|
|
|
.jsonPath("$[1].name").isEqualTo("Jason"); |
|
|
|
.jsonPath("$[1].name").isEqualTo("Jason"); |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
|
|
|
|
.Kotlin |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
client.get().uri("/persons") |
|
|
|
|
|
|
|
.exchange() |
|
|
|
|
|
|
|
.expectStatus().isOk() |
|
|
|
|
|
|
|
.expectBody() |
|
|
|
|
|
|
|
.jsonPath("$[0].name").isEqualTo("Jane") |
|
|
|
|
|
|
|
.jsonPath("$[1].name").isEqualTo("Jason") |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -262,8 +386,8 @@ To test infinite streams (for example, `"text/event-stream"` or `"application/st |
|
|
|
you need to exit the chained API (by using `returnResult`), immediately after the response status |
|
|
|
you need to exit the chained API (by using `returnResult`), immediately after the response status |
|
|
|
and header assertions, as the following example shows: |
|
|
|
and header assertions, as the following example shows: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,intent=0] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
.Java |
|
|
|
---- |
|
|
|
---- |
|
|
|
FluxExchangeResult<MyEvent> result = client.get().uri("/events") |
|
|
|
FluxExchangeResult<MyEvent> result = client.get().uri("/events") |
|
|
|
.accept(TEXT_EVENT_STREAM) |
|
|
|
.accept(TEXT_EVENT_STREAM) |
|
|
|
@ -272,15 +396,26 @@ and header assertions, as the following example shows: |
|
|
|
.returnResult(MyEvent.class); |
|
|
|
.returnResult(MyEvent.class); |
|
|
|
|
|
|
|
|
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
|
|
|
|
.Kotlin |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
import org.springframework.test.web.reactive.server.returnResult |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val result = client.get().uri("/events") |
|
|
|
|
|
|
|
.accept(TEXT_EVENT_STREAM) |
|
|
|
|
|
|
|
.exchange() |
|
|
|
|
|
|
|
.expectStatus().isOk() |
|
|
|
|
|
|
|
.returnResult<MyEvent>() |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
Now you can consume the `Flux<T>`, assert decoded objects as they come, and then |
|
|
|
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` |
|
|
|
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: |
|
|
|
from the `reactor-test` module to do that, as the following example shows: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,intent=0] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
.Java |
|
|
|
---- |
|
|
|
---- |
|
|
|
Flux<Event> eventFux = result.getResponseBody(); |
|
|
|
Flux<Event> eventFlux = result.getResponseBody(); |
|
|
|
|
|
|
|
|
|
|
|
StepVerifier.create(eventFlux) |
|
|
|
StepVerifier.create(eventFlux) |
|
|
|
.expectNext(person) |
|
|
|
.expectNext(person) |
|
|
|
@ -289,6 +424,18 @@ from the `reactor-test` module to do that, as the following example shows: |
|
|
|
.thenCancel() |
|
|
|
.thenCancel() |
|
|
|
.verify(); |
|
|
|
.verify(); |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
|
|
|
|
.Kotlin |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
val eventFlux = result.getResponseBody() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StepVerifier.create(eventFlux) |
|
|
|
|
|
|
|
.expectNext(person) |
|
|
|
|
|
|
|
.expectNextCount(4) |
|
|
|
|
|
|
|
.consumeNextWith { p -> ... } |
|
|
|
|
|
|
|
.thenCancel() |
|
|
|
|
|
|
|
.verify() |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|