For the latest stable version, please use spring-cloud-contract 4.2.0! |
Spring Cloud Contract WireMock
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.
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.
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
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!"); } }
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.
|
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).
|
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:
@AutoConfigureWireMock(port = 0, stubs = "classpath*:/META-INF...
Using Files to Specify the Stub Bodies
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.
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 .
|
The value of files has no
effect on the stubs loaded explicitly from the stubs attribute.
|
Alternative: Using JUnit Rules
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 example shows:
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 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).
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();
}
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));
...
}
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.
To disable the custom RestTemplateBuilder
, set the wiremock.rest-template-ssl-enabled
property to false
.
WireMock and Spring MVC Mocks
Spring Cloud Contract provides a convenience class that can load JSON WireMock stubs into
a Spring MockRestServiceServer
. The following project shows that.
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 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.
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).