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
}
}
- 指定要加載的配置
- 注入配置
- 創建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文檔,以獲取有關如何使用正文準備請求的示例,包括提交表單數據,多部分請求等。
作者
個人從事金融行業,就職過易極付、思建科技、某網約車平臺等重慶一流技術團隊,目前就職於某銀行負責統一支付系統建設。自身對金融行業有強烈的愛好。同時也實踐大數據、數據存儲、自動化集成和部署、分佈式微服務、響應式編程、人工智能等領域。同時也熱衷於技術分享創立公眾號和博客站點對知識體系進行分享。關注公眾號:青年IT男 獲取最新技術文章推送!
博客地址: http://youngitman.tech
CSDN: https://blog.csdn.net/liyong1028826685
微信公眾號:
技術交流群: