Spring Cloud Contract WireMock
Modules giving you the possibility to use WireMock with different servers by using the "ambient" server embedded in a Spring Boot application. Check out the samples for more details.
Important | The Spring Cloud Release Train BOM imports spring-cloud-contract-dependencies which in turn has exclusions for the dependencies needed by WireMock. This might lead to a situation that even if you’re not using Spring Cloud Contract then your dependencies will be influenced anyways. |
---|---|
If you have a Spring Boot application that uses Tomcat as an embedded server, for example (the default with spring-boot-starter-web
), then you can simply add spring-cloud-contract-wiremock
to your classpath and add @AutoConfigureWireMock
in order to be able to use Wiremock in your tests. Wiremock runs as a stub server and you can register stub behaviour using a Java API or via static JSON declarations as part of your test. Here’s a simple example:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureWireMock(port = 0)
public class WiremockForDocsTests {
// A service that calls out over HTTP
@Autowired private Service service;
// Using the WireMock APIs in the normal way:
@Test
public void contextLoads() throws Exception {
// Stubbing WireMock
stubFor(get(urlEqualTo("/resource"))
.willReturn(aResponse().withHeader("Content-Type", "text/plain").withBody("Hello World!")));
// We're asserting if WireMock responded properly
assertThat(this.service.go()).isEqualTo("Hello World!");
}
}
To start the stub server on a different port use @AutoConfigureWireMock(port=9999)
(for example), and for a random port use the value 0. The stub server port will be bindable in the test application context as "wiremock.server.port". Using @AutoConfigureWireMock
adds a bean of type WiremockConfiguration
to your test application context, where it will be cached in between methods and classes having the same context, just like for normal Spring integration tests.
Registering Stubs Automatically
If you use @AutoConfigureWireMock
then it will register WireMock JSON stubs from the file system or classpath, by default from file:src/test/resources/mappings
. You can customize the locations using the stubs
attribute in the annotation, which can be a resource pattern (ant-style) or a directory, in which case ***/**.json
is appended. Example:
<pre>@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!");
}
}</pre>
Note | Actually WireMock always loads mappings from src/test/resources/mappings as well as the custom locations in the stubs attribute. To change this behaviour you have to also specify a files root as described next. |
---|---|
Using Files to Specify the Stub Bodies
WireMock can read response bodies from files on the classpath or file system. In that case you will 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 src/test/resources/__files
by default. To customize this location you can set the files
attribute in the @AutoConfigureWireMock
annotation to the location of the parent directory (i.e. the place __files
is a subdirectory). You can use Spring resource notation to refer to file:…
or classpath:…
locations (but generic URLs are not supported). A list of values can be given and WireMock will resolve the first file that exists when it needs to find a response body.
Note | when you configure the files root, then it affects the automatic loading of stubs as well (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, using JUnit @Rules
to start and stop the server, just use the WireMockSpring
convenience class to obtain an Options
instance:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class WiremockForDocsClassRuleTests {
// Start WireMock on some dynamic port
// for some reason `dynamicPort()` is not working properly
@ClassRule
public static WireMockClassRule wiremock = new WireMockClassRule(
WireMockSpring.options().dynamicPort());
// A service that calls out over HTTP to localhost:${wiremock.port}
@Autowired
private Service service;
// Using the WireMock APIs in the normal way:
@Test
public void contextLoads() throws Exception {
// Stubbing WireMock
wiremock.stubFor(get(urlEqualTo("/resource"))
.willReturn(aResponse().withHeader("Content-Type", "text/plain").withBody("Hello World!")));
// We're asserting if WireMock responded properly
assertThat(this.service.go()).isEqualTo("Hello World!");
}
}
The use @ClassRule
means that the server will shut down after all the methods in this class.