I encountered the same problem, and this is the solution I came up with.
According to documentation,
WebTestClient is a thin shell around WebClient, using it to perform
requests and exposing a dedicated, fluent API for verifying
responses.
To my understanding it is geared for testing the response in a similar fashion as assertThat
assertations do.
In my solution I instead use WebClient
for extracting values.
The code snippet below should explain all the details. Note that it is just a generalized example, you should tailor it for your needs.
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import static org.springframework.http.MediaType.APPLICATION_JSON;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class FooTest {
@Autowired
private WebTestClient webTestClient;
/**
* The port of the server. It starts on a RANDOM_PORT. @LocalServerPort is a way to find out what this port is.
*/
@LocalServerPort
private int port;
@Test
void someTestMethod() throws JSONException {
// Create the request body that we'll send with the POST request.
String postRequestBody = new JSONObject()
.put("JsonField_1", "value a")
.put("JsonFiled_2", "value b")
// .put("any_additional_json_fields", "with_any_values")
.toString();
// The URI where we'll send the request to.
String postRequestUri = "http://localhost:" + String.valueOf(port) + "/some_api";
// Send a POST request, and save the response.
TypeOfResponseWeExpect response = WebClient.create()
.post()
.uri(postRequestUri)
.contentType(APPLICATION_JSON)
.accept(APPLICATION_JSON)
.body(BodyInserters.fromValue(postRequestBody))
.retrieve()
.bodyToMono(TypeOfResponseWeExpect.class)
.block();
// And now we can extract any values from the response.
long extractedId = response.getId();
String token = response.getToken();
FooField fooField = response.getFoo();
BarField barField = response.getBar();
// Now we can use the extracted id field, or any field from the response.
webTestClient
.get()
.uri(uriBuilder -> uriBuilder.path("/api/messages/{id}").build(extractedId))
.headers(http -> http.setBearerAuth(token))
.exchange()
.expectStatus().isOk();
}
}
Edit: After some further tries, I found a way to extract the response with WebTestClient too:
TypeOfResponseWeExpect response = this.webTestClient
.post()
.uri(postRequestUri)
.contentType(APPLICATION_JSON)
.accept(APPLICATION_JSON)
.body(BodyInserters.fromValue(postRequestBody))
.exchange()
.expectBody(TypeOfResponseWeExpect.class)
.returnResult()
.getResponseBody();