測試用戶端應用程式

您可以使用用戶端測試來測試在內部使用 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 引數,該引數指定計數範圍(例如,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()

在上述範例中,我們使用 RestTemplate 中的 ClientHttpRequestFactory MockRestServiceServer 將其替換為模擬回應的不同工廠之前建立 ExecutingResponseCreator。然後,我們使用兩種回應類型定義期望

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

  • 透過呼叫 /quoteOfTheDay 端點取得的回應

在第二種情況下,請求會透過先前擷取的 ClientHttpRequestFactory 執行。這會產生一個回應,該回應例如可能來自實際的遠端伺服器,具體取決於 RestTemplate 最初的組態方式。

靜態匯入

與伺服器端測試一樣,用戶端測試的 Fluent API 需要一些靜態匯入。這些靜態匯入很容易透過搜尋 MockRest* 找到。Eclipse 使用者應在 Eclipse 偏好設定的 Java → 編輯器 → 內容輔助 → 我的最愛下,將 MockRestRequestMatchers.*MockRestResponseCreators.* 新增為「最愛的靜態成員」。這允許在輸入靜態方法名稱的第一個字元後使用內容輔助。其他 IDE(例如 IntelliJ)可能不需要任何額外的組態。檢查是否支援靜態成員的程式碼完成。

用戶端 REST 測試的更多範例

Spring MVC Test 自己的測試包括 用戶端 REST 測試的範例測試