|
此版本仍在开发中,目前尚不被视为稳定版本。如需最新稳定版本,请使用 spring-cloud-contract 5.0.2! |
Spring Cloud Contract WireMock
Spring Cloud Contract WireMock 模块允许您在 Spring Boot 应用程序中使用 WireMock。欲了解更多信息,请查看 Spring Cloud Contract 的存储库中的 示例子文件夹。
如果您有一个使用 Tomcat 作为嵌入式服务器的 Spring Boot 应用程序(这是默认配置,即 spring-boot-starter-web),您可以将 spring-cloud-starter-contract-stub-runner 添加到类路径中,并将 @AutoConfigureWireMock 添加到您的测试中,以在测试中使用 WireMock。WireMock 作为一个模拟服务器运行,您可以通过 Java API 或通过将静态 JSON 声明作为测试的一部分来注册模拟行为。
要以不同端口启动存根服务器,请使用(例如)@AutoConfigureWireMock(port=9999)。若需随机端口,请将值设为 0。存根服务器端口可在测试应用上下文中通过 wiremock.server.port 属性进行绑定。使用 @AutoConfigureWireMock 可将类型为 WiremockConfiguration 的 Bean 添加至您的测试应用上下文,该 Bean 将在具有相同上下文的方法和类之间进行缓存。Spring 集成测试亦遵循相同规则。此外,您还可以将类型为 WireMockServer 的 Bean 注入到您的测试中。已注册的 WireMock 服务器会在每个测试类结束后重置。但若需在每个测试方法后重置它,请将 wiremock.reset-mappings-after-each-test 属性设为 true。
自动注册存根
如果您使用 @AutoConfigureWireMock,它将从文件系统或类路径中注册 WireMock JSON 存根(默认情况下,从 file:src/test/resources/mappings 中读取)。您可以通过在注解中使用 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 属性控制)也进行重置。 |
如果您使用 Spring Cloud Contract 的默认存根 JAR 文件,您的存根将存储在 /META-INF/group-id/artifact-id/versions/mappings/ 文件夹中。如果您希望从该位置注册所有存根(包括所有嵌入式 JAR 文件中的存根),可以使用以下语法:
@AutoConfigureWireMock(port = 0, stubs = "classpath*:/META-INF...
使用文件指定存根实现
WireMock 可以从类路径或文件系统中的文件读取响应体。在文件系统的情况下,您可以在 JSON DSL 中看到响应具有 bodyFileName 而非(字面)body。这些文件是相对于一个根目录解析的(默认情况下为 src/test/resources/__files)。若要自定义此位置,您可以将 files 属性设置为 @AutoConfigureWireMock 注解中父目录的位置(换句话说,__files 是子目录)。您可以使用 Spring 资源语法来引用 file:… 或 classpath:… 的位置。不支持通用 URL。可以提供多个值的列表——在这种情况下,当 WireMock 需要查找响应体时,它会解析第一个存在的文件。
当你配置 files 根目录时,它也会对存根的自动加载产生影响,因为这些存根位于根目录下的一个名为 mappings 的子目录中。 |
值 files 对从 stubs 属性显式加载的存根没有影响。 |
替代方案:使用 JUnit 规则
为了获得更传统的 WireMock 使用体验,您可以使用 JUnit @Rules 来启动和停止服务器。为此,请使用 WireMockSpring 这个便捷类来获取一个 Options 实例,如下 示例 所示:
The @ClassRule means that the server shuts down after all the methods in this class have been run.
Rest Template 的宽松 SSL 验证
WireMock 允许您使用 https URL 协议来模拟一个“安全”的服务器。如果您的应用程序希望在集成测试中与该模拟服务器通信,会发现 SSL 证书无效(这通常是自安装证书的常见问题)。最佳选择通常是重新配置客户端以使用 http。如果此方法不可行,您可以要求 Spring 配置一个忽略 SSL 验证错误的 HTTP 客户端(仅在测试环境中如此操作)。
为了以最少的麻烦实现此功能,您需要在应用程序中使用 Spring Boot RestTemplateBuilder,如下例所示:
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
您需要 RestTemplateBuilder,因为构建器会通过回调传递以初始化它,从而可以在该点设置 SSL 验证。如果您在测试中使用 @AutoConfigureWireMock 注解或存根运行器,此操作会自动发生。如果您采用 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 模拟
Spring Cloud Contract 提供了一个便捷的类,可将 JSON WireMock 模拟数据加载到 Spring MockRestServiceServer 中。以下 项目 展示了这一点。
值 baseUrl 会被添加到所有模拟调用的前面,而 stubs() 方法则接受一个存根路径资源模式作为参数。在前面的例子中,定义在 /stubs/resource.json 处的存根将被加载到模拟服务器中。如果 RestTemplate 被要求访问 example.org/,它将返回在该 URL 处所声明的响应。可以指定多个存根模式,每个模式可以是一个目录(用于递归列出所有 .json),一个固定文件名(如前面例子所示),或一个 Ant 风格的模式。JSON 格式为标准的 WireMock 格式,您可以在 WireMock 官方网站 上了解更多信息。
目前,Spring Cloud Contract Verifier 支持 Tomcat、Jetty 和 Undertow 作为 Spring Boot 嵌入式服务器,而 WireMock 本身对特定版本的 Jetty(当前为 9.2)具有“原生”支持。若要使用原生 Jetty,您需要添加原生 WireMock 依赖项,并排除 Spring Boot 容器(如果存在的话)。