Using WireMock with Pact
Documentation / java / solutions / pact
WireMock Pact
WireMock Pact will get the requests from WireMock and create Pact JSON files on the filesystem. The Pact JSON can be published to a Pactflow broker.
WireMock Pact contains:
wiremock-pact-lib- A library that can transform WireMock ServeEvent:s to Pact JSON.wiremock-pact-extension-junit5- A WireMock extension, and JUnit 5, that is intended to ease usage of the library.wiremock-pact-example-springboot-app- A SpringBoot application that shows how it can be used.
WireMock Pact is released to Maven Central. And available on GitHub.
Usage - Junit 5
The extension is both a WireMock extension and a JUnit 5 extension. When using wiremock-spring-boot it can be configured like this in a base class of your tests:
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import com.maciejwalkowiak.wiremock.spring.ConfigureWireMock;
import com.maciejwalkowiak.wiremock.spring.EnableWireMock;
import com.maciejwalkowiak.wiremock.spring.WireMockConfigurationCustomizer;
import org.junit.jupiter.api.extension.RegisterExtension;
import se.bjurr.wiremockpact.wiremockpactextensionjunit5.WireMockPactExtension;
import se.bjurr.wiremockpact.wiremockpactlib.api.WireMockPactConfig;
@EnableWireMock({
@ConfigureWireMock(
name = "wiremock-service-name",
property = "wiremock.server.url",
stubLocation = "wiremock",
configurationCustomizers = {WireMockPactBaseTest.class})
})
public class WireMockPactBaseTest implements WireMockConfigurationCustomizer {
@RegisterExtension
static WireMockPactExtension WIREMOCK_PACT_EXTENSION =
new WireMockPactExtension(
WireMockPactConfig.builder() //
.setConsumerDefaultValue("WireMockPactExample") //
.setProviderDefaultValue("UnknownProvider") //
.setPactJsonFolder("src/test/resources/pact-json"));
@Override
public void customize(
final WireMockConfiguration configuration, final ConfigureWireMock options) {
configuration.extensions(WIREMOCK_PACT_EXTENSION);
}
}
Usage - Library
It can be used as a library.
public class ExampleTest {
private static WireMockServer server;
private static WireMockPactApi wireMockPactApi;
@BeforeAll
public static void beforeEach() throws IOException {
server = new WireMockServer();
server.start();
stubFor(
post(anyUrl())
.willReturn(
ok()
.withHeader("content-type", "application/json")
.withBody("""
{"a":"b"}
"""))
.withMetadata(
new Metadata(
Map.of(
WireMockPactMetadata.METADATA_ATTR,
new WireMockPactMetadata()
.setProvider("some-specific-provider")))));
wireMockPactApi =
WireMockPactApi.create(
new WireMockPactConfig()
.setConsumerDefaultValue("my-service")
.setProviderDefaultValue("unknown-service")
.setPactJsonFolder("the/pact-json/folder"));
wireMockPactApi.clearAllSaved();
}
@Test
public void testInvoke() {
// Do stuff that invokes WireMock...
}
@AfterAll
public static void after() {
for (final ServeEvent serveEvent : server.getAllServeEvents()) {
wireMockPactApi.addServeEvent(serveEvent);
}
// Save pact-json to folder given in WireMockPactApi
wireMockPactApi.saveAll();
server.stop();
}
}
Mappings metadata - Set provider in mapping
You can adjust any mappings file like this to specify the provider of a mapping in its metadata field:
{
"id" : "d68fb4e2-48ed-40d2-bc73-0a18f54f3ece",
"request" : {
"urlPattern" : "/animals/1",
"method" : "GET"
},
"response" : {
"status" : 202
},
"uuid" : "d68fb4e2-48ed-40d2-bc73-0a18f54f3ece",
+ "metadata": {
+ "wireMockPactSettings": {
+ "provider":"some-other-system"
+ }
+ }
}
Or programmatically:
stubFor(
post(anyUrl())
.withMetadata(
new Metadata(
Map.of(
WireMockPactMetadata.METADATA_ATTR,
new WireMockPactMetadata()
.setProvider("some-specific-provider")))));
Publishing to Pact broker
Pact has a CLI tool that can be used for publishing the contracts. But it requires Ruby or Docker. If you don't have that, perhaps curl is an option. There is a shell script here that can also be used via NPM.
You may want to use something like git-changelog-command-line to get the next version.
There is a test-server at https://test.pactflow.io/ that can be accessed with user dXfltyFMgNOFZAxr8io9wJ37iUpY42M and password O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1.
current_version=$(npx git-changelog-command-line \
--patch-version-pattern "^fix.*" \
--print-current-version)
git_hash=`git rev-parse --short HEAD`
participant_version_number="$current_version-$git_hash"
npx pactflow-publish-sh \
--username=dXfltyFMgNOFZAxr8io9wJ37iUpY42M \
--password=O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1 \
--pactflow-broker-url=https://test.pactflow.io/contracts/publish \
--build-url=http://whatever/ \
--pact-json-folder=wiremock-pact-example-springboot-app/src/test/resources/pact-json \
--participant-version-number=$participant_version_number
Useful pages
- WireMock on Java and JVM - Most of JVM generic solutions are applicable to Spring Boot development too