33

Spring 5 中文解析测试篇-WebTestClient

 4 years ago
source link: http://youngitman.tech/2020/09/14/spring-5-中文解析测试篇-webtestclient/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

3.7 WebTestClient

WebTestClient 是围绕 WebClient 的薄壳,可用于执行请求并公开专用的流利API来验证响应。 WebTestClient 通过使用模拟请求和响应绑定到 WebFlux 应用程序,或者它可以通过HTTP连接测试任何Web服务器。

Kotlin用户:请 参阅本节WebTestClient 的使用有关。

3.7.1 安装

要创建 WebTestClient ,必须选择多个服务器设置选项之一。实际上,你是在配置 WebFlux 应用程序以绑定到该URL,还是使用URL连接到正在运行的服务器。

绑定到控制器

以下示例显示如何创建服务器设置以一次测试一个 @Controller

client = WebTestClient.bindToController(new TestController()).build();

前面的示例加载 WebFlux Java配置 并注册给定的控制器。使用模拟请求和响应对象,可以在没有HTTP服务器的情况下测试生成的 WebFlux 应用程序。构建器上有更多方法可以定制默认 WebFlux Java配置。

绑定到路由器功能

以下示例显示了如何通过 RouterFunction 设置服务器:

RouterFunction<?> route = ...
client = WebTestClient.bindToRouterFunction(route).build();

在内部,配置被传递到 RouterFunctions.toWebHandler 。使用模拟请求和响应对象,可以在没有HTTP服务器的情况下测试生成的 WebFlux 应用程序。

绑定到ApplicationContext

以下示例显示了如何通过应用程序或其部分子集的Spring配置来设置服务器:

@SpringJUnitConfig(WebConfig.class) //1
class MyTests {

    WebTestClient client;

    @BeforeEach
    void setUp(ApplicationContext context) {  //2
        client = WebTestClient.bindToApplicationContext(context).build(); //3
    }
}
  1. 指定要加载的配置
  2. 注入配置
  3. 创建WebTestClient

在内部,配置被传递到 WebHttpHandlerBuilder 以建立请求处理链。有关更多详细信息,请参见 WebHandler API 。使用模拟请求和响应对象,可以在没有HTTP服务器的情况下测试生成的 WebFlux 应用程序。

绑定到服务器

以下服务器设置选项使你可以连接到正在运行的服务器:

client = WebTestClient.bindToServer().baseUrl("http://localhost:8080").build();

客户端构建者

除了前面介绍的服务器设置选项之外,你还可以配置客户端选项、包括基本URL、默认标头,客户端过滤器等。这些选项在 bindToServer 之后很容易获得。对于所有其他服务器,你需要使用 configureClient() 从服务器配置过渡到客户端配置,如下所示:

client = WebTestClient.bindToController(new TestController())
        .configureClient()
        .baseUrl("/test")
        .build();

3.7.2 写测试

WebTestClient提供了与 WebClient 相同的API,直到使用 exchange() 执行请求为止。 exchange() 之后是链接的API工作流,用于验证响应。

通常,首先声明响应状态和标头,如下所示:

client.get().uri("/persons/1")
            .accept(MediaType.APPLICATION_JSON)
            .exchange()
            .expectStatus().isOk()
            .expectHeader().contentType(MediaType.APPLICATION_JSON)

然后,你指定如何解码和使用响应主体:

  • ExpectBody(Class <T>) :解码为单个对象。
  • ExpectBodyList(Class <T>) :解码并将对象收集到 List <T>
  • ExpectBody() :解码为 byte [] 以获取JSON内容或一个空的正文。

然后,你可以为主体使用内置的断言。以下示例显示了一种方法:

client.get().uri("/persons")
        .exchange()
        .expectStatus().isOk()
        .expectBodyList(Person.class).hasSize(3).contains(person);

你还可以超越内置的断言并创建自己的断言,如以下示例所示:

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)...
        });

你还可以退出工作流程并获得结果,如下所示:

EntityExchangeResult<Person> result = client.get().uri("/persons/1")
        .exchange()
        .expectStatus().isOk()
        .expectBody(Person.class)
        .returnResult();

当你需要使用泛型解码为目标类型时,请寻找接受 ParameterizedTypeReference 而不是 Class <T> 的重载方法。

无内容

如果响应没有内容(或者你不在乎),请使用 Void.class ,以确保释放资源。以下示例显示了如何执行此操作:

client.get().uri("/persons/123")
        .exchange()
        .expectStatus().isNotFound()
        .expectBody(Void.class);

或者,如果要断言没有响应内容,则可以使用类似于以下内容的代码:

client.post().uri("/persons")
        .body(personMono, Person.class)
        .exchange()
        .expectStatus().isCreated()
        .expectBody().isEmpty();

JSON内容

当你使用ExpectBody()时,响应以 byte[] 的形式使用。这对于原始内容声明很有用。例如,你可以使用JSONAssert来验证JSON内容,如下所示:

client.get().uri("/persons/1")
        .exchange()
        .expectStatus().isOk()
        .expectBody()
        .json("{\"name\":\"Jane\"}")

你还可以使用 JSONPath 表达式,如下所示:

client.get().uri("/persons")
        .exchange()
        .expectStatus().isOk()
        .expectBody()
        .jsonPath("$[0].name").isEqualTo("Jane")
        .jsonPath("$[1].name").isEqualTo("Jason");

流式响应

要测试无限流(例如,“ text/event-stream ”或“ application/stream + json ”),你需要在响应状态和响应头断言之后立即退出链接的API(通过使用 returnResult ),如下所示示例显示:

FluxExchangeResult<MyEvent> result = client.get().uri("/events")
        .accept(TEXT_EVENT_STREAM)
        .exchange()
        .expectStatus().isOk()
        .returnResult(MyEvent.class);

现在,你可以使用Flux ,在到达解码对象时对其进行断言,然后在达到测试目标时在某个时候取消。我们建议使用反应堆测试模块中的StepVerifier进行此操作,如以下示例所示:

Flux<Event> eventFlux = result.getResponseBody();

StepVerifier.create(eventFlux)
        .expectNext(person)
        .expectNextCount(4)
        .consumeNextWith(p -> ...)
        .thenCancel()
        .verify();

请求体

当涉及到构建请求时, WebTestClient 提供了与WebClient相同的API,实现主要是简单的传递。请参阅 WebClient文档 ,以获取有关如何使用正文准备请求的示例,包括提交表单数据,多部分请求等。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK