測試客戶端應用程式
您可以使用客戶端測試來測試內部使用 RestTemplate
的程式碼。核心思想是宣告預期的請求並提供“存根”響應,這樣您就可以專注於獨立測試程式碼(即無需執行伺服器)。以下示例展示瞭如何實現:
-
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
引數,用於指定計數範圍(例如,once
、manyTimes
、max
、min
、between
等)。以下示例使用了 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()
在前面的示例中,我們在 MockRestServiceServer
用不同的工廠替換 RestTemplate
的 ClientHttpRequestFactory
之前,使用 RestTemplate
的工廠建立了 ExecutingResponseCreator
。然後,我們定義了兩種響應型別的期望:
-
對於
/profile
端點,返回一個存根200
響應(不會執行實際請求) -
透過呼叫
/quoteOfTheDay
端點獲得的響應
在第二種情況下,請求透過先前捕獲的 ClientHttpRequestFactory
執行。根據 RestTemplate
最初的配置方式,這會生成一個響應,該響應可能來自實際的遠端伺服器。
靜態匯入
與伺服器端測試一樣,客戶端測試的流暢 API 需要一些靜態匯入。透過搜尋 MockRest*
很容易找到它們。Eclipse 使用者應將 MockRestRequestMatchers.*
和 MockRestResponseCreators.*
新增到 Eclipse 偏好設定中 Java → Editor → Content Assist → Favorites 下的“favorite static members”(收藏夾靜態成員)。這允許在輸入靜態方法名稱的第一個字元後使用內容輔助。其他 IDE(如 IntelliJ)可能不需要任何額外的配置。請檢查對靜態成員程式碼補全的支援。
客戶端 REST 測試的更多示例
Spring MVC Test 自己的測試包含客戶端 REST 測試的示例。