Spring Cloud Contract WireMock

Spring Cloud Contract WireMock 模块允许你在 Spring Boot 应用程序中使用 WireMock。 有关详细信息,请查看 Spring Cloud Contract 的存储库 samples subfolder。 如果你有一个将 Tomcat 用作嵌入式服务器(这在 spring-boot-starter-web 中是默认的)的 Spring Boot 应用程序,你可以向你的类路径添加 spring-cloud-starter-contract-stub-runner,并添加 @AutoConfigureWireMock,以便在你的测试中使用 Wiremock。Wiremock 以存根服务器运行,并且你可以使用 Java API 或使用静态 JSON 声明作为你测试的一部分来注册存根行为。 要在不同的端口上启动存根服务器,请使用(例如)@AutoConfigureWireMock(port=9999)。对于随机端口,使用值为 0。存根服务器端口可以使用 wiremock.server.port 属性在测试应用程序上下文中绑定。使用 @AutoConfigureWireMockWiremockConfiguration 类型的一个 bean 添加到你的测试应用程序上下文中,其中它被缓存在具有相同上下文的那些方法和类之间。Spring 集成测试也是这样。此外,你可以将 WireMockServer 类型的一个 bean 注入到你的测试中。在每个测试类之后,都会重置已注册的 WireMock 服务器。不过,如果你需要在每个测试方法之后重置它,请将 wiremock.reset-mappings-after-each-test 属性设置为 true

Registering Stubs Automatically

如果你使用 @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 始终从 as well as src/test/resources/mappingsstubs 属性中的自定义位置加载映射。要更改此行为,您还可以指定文件根,如 next section of this document 中所述。

此外,`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 中,可以使用以下语法:

Unresolved directive in project-features-wiremock.adoc - include::{wiremock_tests}/src/test/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMockFilesApplicationWithUrlResourceTests.java[]

Using Files to Specify the Stub Bodies

WireMock 可以从类路径或文件系统上的文件读取响应主体。在文件系统的情况下,你可以在 JSON DSL 中看到响应具有 bodyFileName 而不是(文字)body。这些文件相对于根目录(默认情况下为 src/test/resources/files)解析。要自定义此位置,可以将 @AutoConfigureWireMock 注释中的 files 属性设置为父目录的位置(换句话说,files 是子目录)。你可以使用 Spring 资源符号来引用 file:…​classpath:…​ 位置。不支持通用 URL。可以给出值列表——在这种情况下,WireMock 将在需要查找响应主体时解析第一个存在的文件。

当您配置`files`根目录时,它也会影响存根的自动加载,因为它们来自名为`mappings`的子目录中的根目录位置。

`files`的值不会影响从`stubs`属性中显式加载的存根。

Alternative: Using JUnit Rules

Для более привычного восприятия WireMock вы можете использовать JUnit @Rules для запуска и остановки сервера. Для этого используйте удобный класс WireMockSpring для получения экземпляра Options, как показано в следующем [примере] {doc_samples_url}:

@ClassRule 意味着服务器将在运行该类中的所有方法后关闭。

Relaxed SSL Validation for Rest Template

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 and Spring MVC Mocks

Spring Cloud Contract предоставляет удобный класс, который может загружать заглушки WireMock JSON в Spring MockRestServiceServer. Это показано в следующем [проекте] {doc_samples_url}.

Значение baseUrl добавляется в начало всех фиктивных вызовов, а метод stubs() принимает в качестве аргумента шаблон ресурса пути заглушки. В приведенном выше примере в фиктивный сервер загружается заглушка, определенная в /stubs/resource.json. Если RestTemplate`запрашивает посещение `https://example.org/, он получает ответы, объявленные по этому URL-адресу. Можно указать более одного шаблона заглушки, каждый из которых может быть каталогом (для рекурсивного списка всех .json), фиксированным именем файла (как в приведенном примере) или шаблоном в стиле Ant. Формат JSON — это обычный формат WireMock, который можно прочитать по адресу WireMock website.

目前,Spring Cloud Contract Verifier 支持 Tomcat、Jetty 和 Undertow 作为 Spring Boot 嵌入式服务器,而 Wiremock 本身对特定版本的 Jetty(当前为 9.2)具有“本机”支持。要使用本机 Jetty,需要添加本机 Wiremock 依赖项并排除 Spring Boot 容器(如果有)。