Skip to content

Commit

Permalink
docs: WireMock Pact
Browse files Browse the repository at this point in the history
  • Loading branch information
tomasbjerre committed Apr 28, 2024
1 parent f30c8e0 commit 18bf450
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 0 deletions.
1 change: 1 addition & 0 deletions _data/doc-categories.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ java:
- running-without-http-server
- jetty-12
- android
- pact

stubbing-and-verifying:
title: Stubbing & Verifying
Expand Down
1 change: 1 addition & 0 deletions _docs/solutions/jvm.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,6 @@ sorted by alphabet:
- [Clojure](https://docs.google.com/document/d/1TQccT9Bk-o2lvRVN8_mMaGttaOnwbYFLkn0DsmwGIOA/edit#heading=h.gvb3rxc1ab9p)
- [Groovy](../groovy)
- [Kotlin](../kotlin)
- [Pact](../pact)
- [Scala](https://docs.google.com/document/d/1TQccT9Bk-o2lvRVN8_mMaGttaOnwbYFLkn0DsmwGIOA/edit#heading=h.gvb3rxc1ab9p)
- [Spring Boot](../spring-boot)
176 changes: 176 additions & 0 deletions _docs/solutions/pact.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
---
layout: solution
title: "Using WireMock with Pact"
meta_title: Running WireMock with Pact | WireMock
description: The recorded invocations on WireMock can be used to generate the JSON files that are needed to publish contracts to the Pactflow broker.
redirect_from:
- "/docs/pact.html"
---

## WireMock Pact

[![Maven Central](https://maven-badges.herokuapp.com/maven-central/se.bjurr.wiremockpact/wiremock-pact/badge.svg)](https://repo1.maven.org/maven2/se/bjurr/wiremockpact)

It will get the requests from [WireMock](https://github.com/wiremock/wiremock/) and create [Pact JSON](https://docs.pact.io/) files on the filesystem. The Pact JSON can be published to a [Pactflow broker](https://test.pactflow.io/) with `curl`, see example in this readme.

This repostory contains:

- `wiremock-pact-lib` - *A library that can transform WireMock [ServeEvent](https://github.com/wiremock/wiremock/blob/master/src/main/java/com/github/tomakehurst/wiremock/stubbing/ServeEvent.java):s to Pact JSON.*
- `wiremock-pact-extension` - *A WireMock extension that is intended to ease usage of the library.*
- `wiremock-pact-example-springboot-app` - *A SpringBoot application that shows how it can be used.*

## Usage - Junit 5

The extension is both a WireMock extension and a JUnit 5 extension. When using [`wiremock-spring-boot`](https://wiremock.org/docs/solutions/spring-boot/) it can be configured like this in a base class of your tests:

```java
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.wiremockpactextension.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.

```java
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](https://github.com/wiremock/spec/blob/main/wiremock/wiremock-admin-api/schemas/stub-mapping.yaml) field:

```diff
{
"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:

```java
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](https://docs.pact.io/pact_broker/publishing_and_retrieving_pacts) 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](https://github.com/tomasbjerre/pactflow-publish-sh) that can also be used [via NPM](https://www.npmjs.com/package/pactflow-publish-sh).

You may want to use something like [git-changelog-command-line](https://github.com/tomasbjerre/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`.

```sh
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](../jvm) - Most of JVM generic solutions are applicable to Spring Boot development too

0 comments on commit 18bf450

Please sign in to comment.