Spring Cloud Contract WireMock

Spring Cloud Contract WireMock 模块允许你在 Spring Boot 应用程序中使用 WireMock。 有关详细信息,请查看 Spring Cloud Contract 的存储库 samples subfolder

The Spring Cloud Contract WireMock modules let you use WireMock in a Spring Boot application. For more detail, check out the Spring Cloud Contract’s repository samples subfolder.

如果你有一个将 Tomcat 用作嵌入式服务器(这在 spring-boot-starter-web 中是默认的)的 Spring Boot 应用程序,你可以向你的类路径添加 spring-cloud-starter-contract-stub-runner,并添加 @AutoConfigureWireMock,以便在你的测试中使用 Wiremock。Wiremock 以存根服务器运行,并且你可以使用 Java API 或使用静态 JSON 声明作为你测试的一部分来注册存根行为。

If you have a Spring Boot application that uses Tomcat as an embedded server (which is the default with spring-boot-starter-web), you can add spring-cloud-starter-contract-stub-runner to your classpath and add @AutoConfigureWireMock to use Wiremock in your tests. Wiremock runs as a stub server, and you can register stub behavior by using a Java API or by using static JSON declarations as part of your test.

要在不同的端口上启动存根服务器,请使用(例如)@AutoConfigureWireMock(port=9999)。对于随机端口,使用值为 0。存根服务器端口可以使用 wiremock.server.port 属性在测试应用程序上下文中绑定。使用 @AutoConfigureWireMockWiremockConfiguration 类型的一个 bean 添加到你的测试应用程序上下文中,其中它被缓存在具有相同上下文的那些方法和类之间。Spring 集成测试也是这样。此外,你可以将 WireMockServer 类型的一个 bean 注入到你的测试中。在每个测试类之后,都会重置已注册的 WireMock 服务器。不过,如果你需要在每个测试方法之后重置它,请将 wiremock.reset-mappings-after-each-test 属性设置为 true

To start the stub server on a different port, use (for example), @AutoConfigureWireMock(port=9999). For a random port, use a value of 0. The stub server port can be bound in the test application context with the wiremock.server.port property. Using @AutoConfigureWireMock adds a bean of type WiremockConfiguration to your test application context, where it is cached between methods and classes that have the same context. The same is true for Spring integration tests. Also, you can inject a bean of type WireMockServer into your test. The registered WireMock server is reset after each test class. However, if you need to reset it after each test method, set the wiremock.reset-mappings-after-each-test property to true.

Registering Stubs Automatically

如果你使用 @AutoConfigureWireMock,它将从文件系统或类路径(默认情况下,从 file:src/test/resources/mappings)注册 WireMock JSON stub。你可以通过在注释中使用 stubs 属性来自定义位置,它可以是 Ant 样式资源模式或目录。如果是目录,则追加 */.json。以下代码显示了一个示例:

If you use @AutoConfigureWireMock, it registers WireMock JSON stubs from the file system or classpath (by default, from file:src/test/resources/mappings). You can customize the locations by using the stubs attribute in the annotation, which can be an Ant-style resource pattern or a directory. In the case of a directory, */.json is appended. The following code shows an example:

@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 中所述。

Actually, WireMock always loads mappings from src/test/resources/mappings as well as the custom locations in the stubs attribute. To change this behavior, you can also specify a file root, as described in the 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`属性保护)重置映射。

Also, the mappings in the stubs location are not considered part of Wiremock’s "default mappings" and calls to com.github.tomakehurst.wiremock.client.WireMock.resetToDefaultMappings during a test do not result in the mappings in the stubs location being included. However, the org.springframework.cloud.contract.wiremock.WireMockTestExecutionListener does reset the mappings (including adding the ones from the stubs location) after every test class and, optionally, after every test method (guarded by the wiremock.reset-mappings-after-each-test property).

如果你使用 Spring Cloud Contract 的默认存根 jar,则你的存根将存储在 /META-INF/group-id/artifact-id/versions/mappings/ 文件夹中。如果你想从该位置注册所有存根,从所有嵌入的 JAR 中,可以使用以下语法:

If you use Spring Cloud Contract’s default stub jars, your stubs are stored in the /META-INF/group-id/artifact-id/versions/mappings/ folder. If you want to register all stubs from that location, from all embedded JARs, you can use the following syntax:

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 将在需要查找响应主体时解析第一个存在的文件。

WireMock can read response bodies from files on the classpath or the file system. In the case of the file system, you can see in the JSON DSL that the response has a bodyFileName instead of a (literal) body. The files are resolved relative to a root directory (by default, src/test/resources/files). To customize this location, you can set the files attribute in the @AutoConfigureWireMock annotation to the location of the parent directory (in other words, files is a subdirectory). You can use a Spring resource notation to refer to file:…​ or classpath:…​ locations. Generic URLs are not supported. A list of values can be given — in which case, WireMock resolves the first file that exists when it needs to find a response body.

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

When you configure the files root, it also affects the automatic loading of stubs, because they come from the root location in a subdirectory called mappings.

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

The value of files has no effect on the stubs loaded explicitly from the stubs attribute.

Alternative: Using JUnit Rules

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

For a more conventional WireMock experience, you can use JUnit @Rules to start and stop the server. To do so, use the WireMockSpring convenience class to obtain an Options instance, as the following {doc_samples_url}[example] shows:

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

The @ClassRule means that the server shuts down after all the methods in this class have been run.

Relaxed SSL Validation for Rest Template

WireMock 允许你使用 https URL 协议存根一个“安全”服务器。如果你的应用程序想在集成测试中与该存根服务器联系,它会发现 SSL 证书无效(自安装证书的常见问题)。通常最好的选择是重新配置客户端以使用 http。如果那不是一个选项,你可以让 Spring 配置一个忽略 SSL 验证错误的 HTTP 客户端(当然,只针对测试)。

WireMock lets you stub a “secure” server with an https URL protocol. If your application wants to contact that stub server in an integration test, it finds that the SSL certificates are not valid (the usual problem with self-installed certificates). The best option is often to re-configure the client to use http. If that is not an option, you can ask Spring to configure an HTTP client that ignores SSL validation errors (do so only for tests, of course).

为了最小的麻烦让此工作,你需要在你的应用程序中使用 Spring Boot RestTemplateBuilder,如下面的示例所示:

To make this work with minimum fuss, you need to use the Spring Boot RestTemplateBuilder in your application, as the following example shows:

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
	return builder.build();
}

你需要 RestTemplateBuilder,因为构建器通过回调传递进行初始化,因此可以在那时在客户端中设置 SSL 验证。如果你使用 @AutoConfigureWireMock 注释或存根运行器,这会自动在你的测试中发生。如果你使用 JUnit @Rule 方法,则还需要添加 @AutoConfigureHttpClient 注释,如下面的示例所示:

You need RestTemplateBuilder because the builder is passed through callbacks to initialize it, so the SSL validation can be set up in the client at that point. This happens automatically in your test if you use the @AutoConfigureWireMock annotation or the stub runner. If you use the JUnit @Rule approach, you need to add the @AutoConfigureHttpClient annotation as well, as the following example shows:

@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 客户端,则不需要注释(但它没有危害)。目前不支持其他客户端,但可能会在以后的版本中添加。

If you use spring-boot-starter-test, you have the Apache HTTP client on the classpath, and it is selected by the RestTemplateBuilder and configured to ignore SSL errors. If you use the default java.net client, you do not need the annotation (but it does no harm). There is currently no support for other clients, but it may be added in future releases.

要禁用自定义 RestTemplateBuilder,请将 wiremock.rest-template-ssl-enabled 属性设置为 false

To disable the custom RestTemplateBuilder, set the wiremock.rest-template-ssl-enabled property to false.

WireMock and Spring MVC Mocks

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

Spring Cloud Contract provides a convenience class that can load JSON WireMock stubs into a Spring MockRestServiceServer. The following {doc_samples_url}[project] shows that.

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

The baseUrl value is prepended to all mock calls, and the stubs() method takes a stub path resource pattern as an argument. In the preceding example, the stub defined at /stubs/resource.json is loaded into the mock server. If the RestTemplate is asked to visit https://example.org/, it gets the responses as being declared at that URL. More than one stub pattern can be specified, and each one can be a directory (for a recursive list of all .json), a fixed filename (as in the preceding example), or an Ant-style pattern. The JSON format is the normal WireMock format, which you can read about at the WireMock website.

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

Currently, the Spring Cloud Contract Verifier supports Tomcat, Jetty, and Undertow as Spring Boot embedded servers, and Wiremock itself has “native” support for a particular version of Jetty (currently 9.2). To use the native Jetty, you need to add the native Wiremock dependencies and exclude the Spring Boot container (if there is one).