天天看點

Spring 5 中文解析測試篇-WebTestClient

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

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文檔

,以擷取有關如何使用正文準備請求的示例,包括送出表單資料,多部分請求等。

作者

個人從事金融行業,就職過易極付、思建科技、某網約車平台等重慶一流技術團隊,目前就職于某銀行負責統一支付系統建設。自身對金融行業有強烈的愛好。同時也實踐大資料、資料存儲、自動化內建和部署、分布式微服務、響應式程式設計、人工智能等領域。同時也熱衷于技術分享創立公衆号和部落格站點對知識體系進行分享。關注公衆号:青年IT男 擷取最新技術文章推送!

部落格位址:

http://youngitman.tech

CSDN:

https://blog.csdn.net/liyong1028826685

微信公衆号:

Spring 5 中文解析測試篇-WebTestClient

技術交流群:

Spring 5 中文解析測試篇-WebTestClient