#spring #spring-boot #spring-test #spring-webtestclient
Вопрос:
С Spring Boot 2.4.2 я использую WebTestClient
для вызова запросов в своих интеграционных тестах.
Это первый запрос, который получает список сообщений:
webTestClient
.get()
.uri("/api/messages")
.headers(http -> http.setBearerAuth(token))
.exchange()
.expectStatus().isOk()
.expectHeader().contentType(APPLICATION_JSON)
.expectBody()
.jsonPath("$.length()").isEqualTo(1)
.jsonPath("$[0].id").isNumber()
.jsonPath("$[0].type").isEqualTo(4);
Теперь я хотел бы вызвать последующий запрос на загрузку определенного сообщения. Для этого мне нужно id
то, что уже было проверено jsonPath("$[0].id")
.
webTestClient
.get()
.uri(uriBuilder -> uriBuilder.path("/api/messages/{id}").build(extractedId))
.headers(http -> http.setBearerAuth(token))
.exchange()
.expectStatus().isOk();
Как я могу извлечь это id
в локальную переменную или иначе, чтобы оно было доступно для второго запроса?
Комментарии:
1. Я просматривал этот пост некоторое время назад, может быть, это может вам помочь. blazemeter.com/blog/…
Ответ №1:
Вы можете проверить их официальные документы на это.
Но немного расширяя ответ, проще всего было бы сделать следующее
val result = webTestClient
.get()
.uri(uriBuilder -> uriBuilder.path("/api/messages/{id}").build(extractedId))
.headers(http -> http.setBearerAuth(token))
.exchange()
.expectStatus().isOk()
.returnResult();
Существуют также способы получения (бесконечного) потока ответов, описанных в документах, что очень похоже на приведенный выше пример.
Комментарии:
1. Насколько я вижу, это возвращает полный ответ и потребует преобразования тела ответа из массива байтов в какой-либо обрабатываемый объект для последующего извлечения параметра. Я больше думал о чем-то вроде «Эй, просто извлеките это единственное значение JSON».
2. Я не уверен , как бы вы это сделали… если вас интересует только это
id
, вы могли бы создать простое POJO только сid
полем и использовать его наexpectBody
том, что скажет ему автоматически преобразовать ответ в это поле. Просто убедитесь, что вы не ошибетесь в неизвестных свойствах.
Ответ №2:
Я столкнулся с той же проблемой, и это решение, которое я придумал.
Согласно документации,
WebTestClient-это тонкая оболочка вокруг WebClient, использующая ее для выполнения запросов и предоставляющая выделенный, свободный API для проверки ответов.
Насколько я понимаю, он предназначен для тестирования ответа таким же образом, как assertThat
и утверждения.
В моем решении я вместо этого использую WebClient
для извлечения значений.
Приведенный ниже фрагмент кода должен объяснить все детали. Обратите внимание, что это всего лишь обобщенный пример, вы должны адаптировать его под свои потребности.
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();
}
}
Правка: После некоторых дальнейших попыток я тоже нашел способ извлечь ответ с помощью WebTestClient:
TypeOfResponseWeExpect response = this.webTestClient
.post()
.uri(postRequestUri)
.contentType(APPLICATION_JSON)
.accept(APPLICATION_JSON)
.body(BodyInserters.fromValue(postRequestBody))
.exchange()
.expectBody(TypeOfResponseWeExpect.class)
.returnResult()
.getResponseBody();