WireMock Spring Boot library drastically simplifies WireMock configuration in a Spring Boot and JUnit 5 application.
- fully declarative WireMock setup
- support for multiple
WireMockServer
instances - one per HTTP client as recommended in the WireMock documentation - automatically sets Spring environment properties
- does not pollute Spring application context with extra beans
Add the dependency to wiremock-spring-boot
:
<dependency>
<groupId>com.maciejwalkowiak.spring</groupId>
<artifactId>wiremock-spring-boot</artifactId>
<version>2.1.3</version>
<scope>test</scope>
</dependency>
Use @EnableWireMock
with @ConfigureWireMock
with tests annotated that use SpringExtension
, like @SpringBootTest
:
@SpringBootTest
@EnableWireMock({
@ConfigureWireMock(name = "user-service", properties = "user-client.url")
})
class TodoControllerTests {
@InjectWireMock("user-service")
private WireMockServer wiremock;
@Value("${user-client.url}")
private String wiremockUrl; // injects the base URL of the WireMockServer instance
@Test
void aTest() {
wiremock.stubFor(...);
}
}
@EnableWireMock
adds test context customizer and enablesWireMockSpringExtension
@ConfigureWireMock
creates aWireMockServer
and passes theWireMockServer#baseUrl
to a Spring environment property with a name given byproperty
.@InjectWireMock
injectsWireMockServer
instance to a test
Note that WireMockServer
instances are not added as beans to Spring application context to avoid polluting it with test-related infrastructure. Instead, instances are kept in a separate store associated with an application context.
WireMock extensions can be registered independently with each @ConfigureWireMock
:
@ConfigureWireMock(name = "...", properties = "...", extensions = { ... })
The concept of single property injection can be described as wiring one WireMockServer
instance to one property.
@SpringBootTest
@EnableWireMock({
@ConfigureWireMock(name = "foo-service", properties = "app.client-apis.foo.base-path"}),
@ConfigureWireMock(name = "bar-service", properties = "app.client-apis.bar.base-path"}),
@ConfigureWireMock(name = "mojo-service", properties = "app.client-apis.mojo.base-path"})
})
class AppIT {
@InjectWireMock("foo-service")
private WireMockServer fooService;
@InjectWireMock("bar-service")
private WireMockServer barService;
@InjectWireMock("mojo-service")
private WireMockServer mojoService;
@Test
void contextLoads() {
// your test code
}
}
The concept of multiple property injection can be described as wiring one WireMockServer
instance to multiple properties.
@SpringBootTest
@EnableWireMock({
@ConfigureWireMock(name = "services", properties = {
"app.client-apis.foo.base-path",
"app.client-apis.bar.base-path",
"app.client-apis.mojo.base-path"})
})
class AppIT {
@InjectWireMock("services")
private WireMockServer services;
@Test
void contextLoads() {
// your test code
}
}
The single property injection provides a high level of isolation when mocking and stubbing 3rd pary RESTful api, because every service
is associated to its own dedicated WireMockServer
instance.
The multiple property injections provides a less complex test setup at the cost of isolation.
By default, each WireMockServer
is configured to load mapping files from a classpath directory wiremock/{server-name}/mappings
.
It can be changed with setting stubLocation
on @ConfigureWireMock
:
@ConfigureWireMock(name = "...", properties = "...", stubLocation = "my-stubs")
Sounds good? Consider ❤️ Sponsoring the project! Thank you!
I looked into and learned few concepts from following projects and resources during the development of this project: