測試客戶端應用程式

要測試使用 RestClientRestTemplate 的程式碼,您可以使用模擬 Web 伺服器,例如 OkHttp MockWebServerWireMock。模擬 Web 伺服器像普通伺服器一樣透過 HTTP 接受請求,這意味著您可以使用與生產環境配置方式相同的 HTTP 客戶端進行測試,這很重要,因為不同客戶端處理網路 I/O 的方式通常存在細微差異。模擬 Web 伺服器的另一個優點是能夠結合生產環境中使用的客戶端,在傳輸層模擬特定的網路問題和條件。

除了專門的模擬 Web 伺服器,Spring 框架歷史上還提供了一個內建選項,透過 MockRestServiceServer 來測試 RestClientRestTemplate。這依賴於使用一個自定義的 ClientHttpRequestFactory 來配置被測試的客戶端,該工廠由模擬伺服器支援,而模擬伺服器又被設定為預期請求併發送“存根”響應,這樣您就可以專注於隔離測試程式碼,而無需執行伺服器。

MockRestServiceServer 早於模擬 Web 伺服器的出現。目前,我們建議使用模擬 Web 伺服器進行更全面的傳輸層和網路條件測試。

以下示例展示了 MockRestServiceServer 的用法

  • Java

  • Kotlin

RestTemplate restTemplate = new RestTemplate();

MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).build();
mockServer.expect(requestTo("/greeting")).andRespond(withSuccess());

// Test code that uses the above RestTemplate ...

mockServer.verify();
val restTemplate = RestTemplate()

val mockServer = MockRestServiceServer.bindTo(restTemplate).build()
mockServer.expect(requestTo("/greeting")).andRespond(withSuccess())

// Test code that uses the above RestTemplate ...

mockServer.verify()

在前面的示例中,MockRestServiceServer(客戶端 REST 測試的核心類)使用自定義的 ClientHttpRequestFactory 配置 RestTemplate,該工廠根據預期斷言實際請求並返回“存根”響應。在這種情況下,我們期望收到對 /greeting 的請求,並希望返回一個帶有 text/plain 內容的 200 響應。我們可以根據需要定義額外的預期請求和存根響應。當我們定義了預期請求和存根響應後,RestTemplate 就可以像往常一樣在客戶端程式碼中使用。測試結束時,可以使用 mockServer.verify() 來驗證所有預期是否都已滿足。

預設情況下,請求的預期順序與宣告預期時的順序一致。您可以在構建伺服器時設定 ignoreExpectOrder 選項,在這種情況下,所有預期(按順序)都會被檢查,以找到與給定請求匹配的預期。這意味著請求可以按任意順序到達。以下示例使用 ignoreExpectOrder

  • Java

  • Kotlin

server = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build();
server = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build()

即使預設情況下請求是無序的,每個請求也只允許執行一次。expect 方法提供了一個過載變體,它接受一個 ExpectedCount 引數,該引數指定一個計數範圍(例如,oncemanyTimesmaxminbetween 等)。以下示例使用 times

  • Java

  • Kotlin

RestTemplate restTemplate = new RestTemplate();

MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).build();
mockServer.expect(times(2), requestTo("/something")).andRespond(withSuccess());
mockServer.expect(times(3), requestTo("/somewhere")).andRespond(withSuccess());

// ...

mockServer.verify();
val restTemplate = RestTemplate()

val mockServer = MockRestServiceServer.bindTo(restTemplate).build()
mockServer.expect(times(2), requestTo("/something")).andRespond(withSuccess())
mockServer.expect(times(3), requestTo("/somewhere")).andRespond(withSuccess())

// ...

mockServer.verify()

請注意,當未設定 ignoreExpectOrder(預設值),因此請求按宣告順序預期時,該順序僅適用於任何預期請求的第一個。例如,如果預期 "/something" 兩次,然後預期 "/somewhere" 三次,那麼在請求 "/somewhere" 之前應該有一個對 "/something" 的請求,但除了隨後的 "/something" 和 "/somewhere" 之外,請求可以在任何時候到來。

作為上述所有方法的替代,客戶端測試支援還提供了一個 ClientHttpRequestFactory 實現,您可以將其配置到 RestTemplate 中,以便將其繫結到 MockMvc 例項。這允許使用實際的伺服器端邏輯處理請求,但無需執行伺服器。以下示例展示瞭如何實現:

  • Java

  • Kotlin

MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
this.restTemplate = new RestTemplate(new MockMvcClientHttpRequestFactory(mockMvc));

// Test code that uses the above RestTemplate ...
val mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build()
restTemplate = RestTemplate(MockMvcClientHttpRequestFactory(mockMvc))

// Test code that uses the above RestTemplate ...

在某些情況下,可能需要對遠端服務執行實際呼叫,而不是模擬響應。以下示例展示瞭如何透過 ExecutingResponseCreator 實現這一點

  • Java

  • Kotlin

RestTemplate restTemplate = new RestTemplate();

// Create ExecutingResponseCreator with the original request factory
ExecutingResponseCreator withActualResponse = new ExecutingResponseCreator(restTemplate.getRequestFactory());

MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).build();
mockServer.expect(requestTo("/profile")).andRespond(withSuccess());
mockServer.expect(requestTo("/quoteOfTheDay")).andRespond(withActualResponse);

// Test code that uses the above RestTemplate ...

mockServer.verify();
val restTemplate = RestTemplate()

// Create ExecutingResponseCreator with the original request factory
val withActualResponse = new ExecutingResponseCreator(restTemplate.getRequestFactory())

val mockServer = MockRestServiceServer.bindTo(restTemplate).build()
mockServer.expect(requestTo("/profile")).andRespond(withSuccess())
mockServer.expect(requestTo("/quoteOfTheDay")).andRespond(withActualResponse)

// Test code that uses the above RestTemplate ...

mockServer.verify()

在前面的例子中,我們使用來自 RestTemplateClientHttpRequestFactory 建立了 ExecutingResponseCreator MockRestServiceServer 用一個模擬響應的工廠替換它之前。然後我們定義了兩種響應的預期:

  • 針對 /profile 端點的存根 200 響應(不會執行實際請求)

  • 透過呼叫 /quoteOfTheDay 端點獲得的響應

在第二種情況下,請求透過之前捕獲的 ClientHttpRequestFactory 執行。這會生成一個響應,例如,可能來自實際的遠端伺服器,具體取決於 RestTemplate 最初的配置方式。

靜態匯入

與伺服器端測試一樣,客戶端測試的流式 API 需要一些靜態匯入。透過搜尋 MockRest* 很容易找到它們。Eclipse 使用者應將 MockRestRequestMatchers.*MockRestResponseCreators.* 新增為 Eclipse 偏好設定中 Java → 編輯器 → 內容輔助 → 收藏夾下的“收藏靜態成員”。這允許在鍵入靜態方法名稱的第一個字元後使用內容輔助。其他 IDE(例如 IntelliJ)可能不需要任何額外的配置。請檢查對靜態成員程式碼完成的支援。

客戶端 REST 測試的更多示例

Spring MVC Test 自己的測試包括 客戶端 REST 測試的示例

© . This site is unofficial and not affiliated with VMware.