Java Consumer Driven Contract Testing

Posted July 3, 2016

Pact-JVM and Gradle in Java


In this post, we will write a Consumer Driven Contract Test between a Gradle Spring Boot dummy provider (RESTful Web Service) and a Gradle dummy consumer.

We will make use of Pact-JVM, which will provide a mock service for the consumer project to generate a Pact, and verification ability for the provider project to verify the Pact.



A Gradle Wrapper allows anybody to work on your project without having to install Gradle. It ensures that the right version of Gradle that the build was designed for is shipped as part of this project repository. First clone the sample repository that includes both the dummy provider and the dummy consumer:

bash-3.2$ git clone
Cloning into 'consumer-driven-contract-testing-example'...
remote: Counting objects: 47, done.
remote: Compressing objects: 100% (33/33), done.
remote: Total 47 (delta 2), reused 42 (delta 1), pack-reused 0
Unpacking objects: 100% (47/47), done.
Checking connectivity... done.

Provider Setup

Navigate into the provider directory, where you will see a sample RESTful Web Service that was built using Sprint Boot and Gradle through this guide. Try running the service by using the following command:

bash-3.2$ ./gradlew clean build && java -jar build/libs/gs-actuator-service-0.1.0.jar
2016-07-03 14:49:59.367  INFO 32114 --- [           main] hello.HelloWorldConfiguration            : Started HelloWorldConfiguration in 6.782 seconds (JVM running for 7.452)  

You should now be able to reach to service by navigating to http://localhost:8080/hello-world or by using curl (observe that the id increments for every request made to the service):

bash-3.2$ curl http://localhost:8080/hello-world
{"id":2,"content":"Hello World!"}

Consumer Setup

The generation of a Pact is always done from the consumer point of view. This generation can be broken down into three parts.

Part 1: Pact Rule

In this part, we define a mock server’s host and port to represent the provider:

public PactRule rule = new PactRule(Configuration.MOCK_HOST, Configuration.MOCK_HOST_PORT, this);
private DslPart helloWorldResults;
Part 2: Pact Fragment

In this part, we construct a Pact Fragment, which defines the expected contract from a provider:

@Pact(state = "HELLO WORLD", provider = Configuration.DUMMY_PROVIDER, consumer = Configuration.DUMMY_CONSUMER)
public PactFragment createFragment(ConsumerPactBuilder.PactDslWithProvider.PactDslWithState builder)
    helloWorldResults = new PactDslJsonBody()

    return builder
            .uponReceiving("get hello world response")
Part 3: Pact Verification

In this part, we ensure that the constructed fragment in Part 2, matches the response from the mock server:

@PactVerification("HELLO WORLD")
public void shouldGetHelloWorld() throws IOException
    DummyConsumer restClient = new DummyConsumer(Configuration.SERVICE_URL);
    assertEquals(helloWorldResults.toString(), restClient.getHelloWorld());

Try generating a Pact using Gradle from the consumer directory:

bash-3.2$ ./gradlew test
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:processTestResources UP-TO-DATE


Total time: 10.67 secs

The Pact will then be generated and stored in the pacts directory, but it looks something like this:

  "provider" : {
    "name" : "dummy-provider"
  "consumer" : {
    "name" : "dummy-consumer"
  "interactions" : [ {
    "providerState" : "HELLO WORLD",
    "description" : "get hello world response",
    "request" : {
      "method" : "GET",
      "path" : "/hello-world"
    "response" : {
      "status" : 200,
      "headers" : {
        "Content-Type" : "application/json;charset=UTF-8"
      "body" : {
        "id" : 5677679801,
        "content" : "dugNvVPasiFRnzqpPNuq"
      "responseMatchingRules" : {
        "$" : {
          "match" : "type"
        "$.body.content" : {
          "match" : "type"
  } ],
  "metadata" : {
    "pact-specification" : {
      "version" : "2.0.0"
    "pact-jvm" : {
      "version" : "2.1.12"


Now that the Pact has been generated by the Consumer, and assuming the Provider (RESTful Web Service) is running. You can run the following command from the provider directory to ensure that the Provider meets all expectations of the Consumer:

bash-3.2$ ./gradlew pactVerify

Verifying a pact between dummy-consumer and dummyProvider
  [Using file /Users/jasonthye/Dev/pact-example-gradle/pacts/dummy-consumer-dummy-provider.json]
         WARNING: State Change ignored as there is no stateChange URL
  get hello world response
    returns a response which
      has status code 200 (OK)
      includes headers
        "Content-Type" with value "application/json;charset=UTF-8" (OK)
      has a matching body (OK)


Total time: 9.936 secs

Full Example