Spring Cloud Contract WireMock
Spring Cloud Contract WireMock 模組讓您可以在 Spring Boot 應用程式中使用 WireMock。如需更多詳細資訊,請查看 Spring Cloud Contract 的儲存庫 samples 子資料夾。
如果您有一個 Spring Boot 應用程式使用 Tomcat 作為嵌入式伺服器(這是 spring-boot-starter-web
的預設設定),您可以將 spring-cloud-starter-contract-stub-runner
新增到您的類別路徑,並新增 @AutoConfigureWireMock
以在您的測試中使用 Wiremock。Wiremock 作為 Stub 伺服器執行,您可以使用 Java API 或使用靜態 JSON 宣告作為測試的一部分來註冊 Stub 行為。
若要在不同的埠上啟動 Stub 伺服器,請使用(例如)@AutoConfigureWireMock(port=9999)
。對於隨機埠,請使用值 0
。Stub 伺服器埠可以使用 wiremock.server.port
屬性在測試應用程式內容中繫結。使用 @AutoConfigureWireMock
會將 WiremockConfiguration
類型的 Bean 新增到您的測試應用程式內容中,它會在具有相同內容的方法和類別之間快取。Spring 整合測試也是如此。此外,您可以將 WireMockServer
類型的 Bean 注入到您的測試中。註冊的 WireMock 伺服器會在每個測試類別之後重設。但是,如果您需要在每個測試方法之後重設它,請將 wiremock.reset-mappings-after-each-test
屬性設定為 true
。
自動註冊 Stub
如果您使用 @AutoConfigureWireMock
,它會從檔案系統或類別路徑(預設情況下,從 file:src/test/resources/mappings
)註冊 WireMock JSON Stub。您可以使用註解中的 stubs
屬性來自訂位置,它可以是 Ant 樣式的資源模式或目錄。在目錄的情況下,會附加 **/
.json。以下程式碼顯示了一個範例
@RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureWireMock(stubs="classpath:/stubs") public class WiremockImportApplicationTests { @Autowired private Service service; @Test public void contextLoads() throws Exception { assertThat(this.service.go()).isEqualTo("Hello World!"); } }
實際上,WireMock 總是會從 src/test/resources/mappings **以及** stubs 屬性中的自訂位置載入對應。若要變更此行為,您也可以指定檔案根目錄,如本文件的 下一節 中所述。 |
此外,stubs 位置中的對應不被視為 Wiremock「預設對應」的一部分,並且在測試期間呼叫 com.github.tomakehurst.wiremock.client.WireMock.resetToDefaultMappings 不會導致包含 stubs 位置中的對應。但是,org.springframework.cloud.contract.wiremock.WireMockTestExecutionListener 會在每個測試類別之後,以及選擇性地在每個測試方法之後(由 wiremock.reset-mappings-after-each-test 屬性保護)重設對應(包括從 stubs 位置新增的對應)。 |
如果您使用 Spring Cloud Contract 的預設 Stub JAR,您的 Stub 會儲存在 /META-INF/group-id/artifact-id/versions/mappings/
資料夾中。如果您想要從所有嵌入式 JAR 註冊該位置的所有 Stub,您可以使用以下語法
@AutoConfigureWireMock(port = 0, stubs = "classpath*:/META-INF...
使用檔案來指定 Stub 主體
WireMock 可以從類別路徑或檔案系統上的檔案讀取回應主體。在檔案系統的情況下,您可以在 JSON DSL 中看到回應具有 bodyFileName
而不是(字面)body
。這些檔案會相對於根目錄(預設情況下為 src/test/resources/__files
)解析。若要自訂此位置,您可以在 @AutoConfigureWireMock
註解中將 files
屬性設定為父目錄的位置(換句話說,__files
是一個子目錄)。您可以使用 Spring 資源表示法來參考 file:…
或 classpath:…
位置。不支援通用 URL。可以給定值清單 — 在這種情況下,WireMock 會在需要尋找回應主體時解析第一個存在的檔案。
當您組態 files 根目錄時,它也會影響 Stub 的自動載入,因為它們來自名為 mappings 的子目錄中的根位置。 |
files 的值對從 stubs 屬性明確載入的 Stub 沒有影響。 |
替代方案:使用 JUnit 規則
為了獲得更傳統的 WireMock 體驗,您可以使用 JUnit @Rules
來啟動和停止伺服器。若要這麼做,請使用 WireMockSpring
便利類別來取得 Options
執行個體,如下列 範例 所示
@ClassRule
表示伺服器會在執行完此類別中的所有方法後關閉。
針對 Rest Template 放鬆 SSL 驗證
WireMock 可讓您使用 https
URL 通訊協定 Stub 「安全」伺服器。如果您的應用程式想要在整合測試中聯絡該 Stub 伺服器,它會發現 SSL 憑證無效(自我安裝憑證的常見問題)。最好的選擇通常是重新組態用戶端以使用 http
。如果這不是一個選項,您可以要求 Spring 組態一個忽略 SSL 驗證錯誤的 HTTP 用戶端(當然,僅針對測試執行此操作)。
為了以最少的麻煩使其運作,您需要在您的應用程式中使用 Spring Boot RestTemplateBuilder
,如下列範例所示
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
您需要 RestTemplateBuilder
,因為建置器會透過回呼傳遞以初始化它,因此可以在該點在用戶端中設定 SSL 驗證。如果您使用 @AutoConfigureWireMock
註解或 Stub Runner,這會在您的測試中自動發生。如果您使用 JUnit @Rule
方法,您也需要新增 @AutoConfigureHttpClient
註解,如下列範例所示
@RunWith(SpringRunner.class)
@SpringBootTest("app.baseUrl=https://localhost:6443")
@AutoConfigureHttpClient
public class WiremockHttpsServerApplicationTests {
@ClassRule
public static WireMockClassRule wiremock = new WireMockClassRule(
WireMockSpring.options().httpsPort(6443));
...
}
如果您使用 spring-boot-starter-test
,您的類別路徑上有 Apache HTTP 用戶端,它會由 RestTemplateBuilder
選取並組態為忽略 SSL 錯誤。如果您使用預設的 java.net
用戶端,則不需要註解(但它沒有害處)。目前不支援其他用戶端,但可能會在未來的版本中新增。
若要停用自訂 RestTemplateBuilder
,請將 wiremock.rest-template-ssl-enabled
屬性設定為 false
。
WireMock 和 Spring MVC Mock
Spring Cloud Contract 提供了一個便利類別,可以將 JSON WireMock Stub 載入到 Spring MockRestServiceServer
中。下列 專案 顯示了這一點。
baseUrl
值會前置到所有 Mock 呼叫,而 stubs()
方法會採用 Stub 路徑資源模式作為引數。在前面的範例中,在 /stubs/resource.json
定義的 Stub 會載入到 Mock 伺服器中。如果要求 RestTemplate
訪問 example.org/
,它會取得在該 URL 宣告的回應。可以指定多個 Stub 模式,每個模式都可以是目錄(用於所有 .json
的遞迴清單)、固定檔名(如前面的範例)或 Ant 樣式模式。JSON 格式是正常的 WireMock 格式,您可以在 WireMock 網站 上閱讀相關資訊。
目前,Spring Cloud Contract Verifier 支援 Tomcat、Jetty 和 Undertow 作為 Spring Boot 嵌入式伺服器,而 Wiremock 本身對特定版本的 Jetty(目前為 9.2)具有「原生」支援。若要使用原生 Jetty,您需要新增原生 Wiremock 依賴項並排除 Spring Boot 容器(如果有的話)。