1

Using pact-jvm - Java

so we have our api which responds with decimal/float values for few parameters. "body": { "status": "api is up.", "totalTime": 0.005939006805419922 }" I tried with regex match but pact body generate the data and that was a mismatch to the decimal that was returned by the actual api.

package pact;
import au.com.dius.pact.consumer.dsl.DslPart;
import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
import au.com.dius.pact.consumer.dsl.PactDslWithProvider;
import au.com.dius.pact.model.PactFragment;
import au.com.dius.pact.consumer.ConsumerPactTest;
import java.util.Map;
import java.util.HashMap;
import au.com.dius.pact.consumer.PactProviderRule;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import org.junit.Rule;
import au.com.dius.pact.consumer.dsl.PactDslJsonArray;

public class PactTest extends ConsumerPactTest {

    @Rule
    public PactProviderRule mockProvider = new PactProviderRule("test_provider", "localhost", 1234, this);
    String v3Path = "/v3";
    private DslPart body = new PactDslJsonBody()
            .stringType("status", "api is up.")
            .decimalType("totalTime", 0.005939006805419922);

    protected PactFragment createFragment(PactDslWithProvider builder) {
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Content-Type", "application/json");

        PactFragment fragment = builder
                .uponReceiving("response")
                .path(v3Path)
                .method("GET")
                .willRespondWith()
                .status(200)
                .headers(headers)
                .body(body)
                .toFragment();
        return fragment;
    }

    @Override
    protected String providerName() {
        return "test_provider";
    }

    @Override
    protected String consumerName() {
        return "test_consumer";
    }

    @Override
    protected void runTest(String url) {
        Map response;
        try {
            response = new ConsumerClient(url).getAsMap(v3Path, "");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

pact generated:

{
"provider": {
    "name": "test_provider"
},
"consumer": {
    "name": "test_consumer"
},
"interactions": [
    {
        "description": "API v3 endpoint response",
        "request": {
            "method": "GET",
            "path": "/v3"
        },
        "response": {
            "status": 200,
            "headers": {
                "Content-Type": "application/json"
            },
            "body": {
                "status": "api is up.",
                "totalTime": 0.005939006805419922
            },
            "matchingRules": {
                "body": {
                    "$.status": {
                        "matchers": [
                            {
                                "match": "type"
                            }
                        ]
                    },
                    "$.totalTime": {
                        "matchers": [
                            {
                                "match": "decimal"
                            }
                        ]
                    }
                }
            }
        }
    }
],
"metadata": {
    "pact-specification": {
        "version": "3.0.0"
    },
    "pact-jvm": {
        "version": "3.5.0-beta.2"
    }
}

}

diff of pact vs the actual response:

0) Verifying a pact between test_consumer and test_provider - API v3 endpoint response returns a response which has a matching body
  $.body.totalTime -> Expected 0.005939006805419922 but received 0.00545501708984375

Diff:

  @1
      "status": "api is up.",
  -    "totalTime": 0.005939006805419922
  +    "totalTime": 0.00545501708984375
  }

so is it possible to do a "eachlike" instead of decimalType to match patterns of those values ? as I looked at eachLike and it takes in a string and an int - https://github.com/DiUS/pact-jvm/blob/master/pact-jvm-consumer/src/main/java/au/com/dius/pact/consumer/dsl/PactDslJsonBody.java#L580

gammabowl
  • 31
  • 5

1 Answers1

1

Looks like you have a version mismatch between the version of the Pact library used in the consumer test, and the version used to verify the provider.

Your consumer test is using V3 of the pact library (3.5.0-beta.2), and is generating V3 matcher expressions ($.totalTime).

When the pact is being verified against the provider, it is expecting V2 expressions ($.body.totalTime), and is then matching using equality as it thinks there is no matcher for that attribute.

If you downgrade to version 3.3.7 in the consumer test, it will default to V2. Or you can force V2 and still use 3.5.0-beta.2 by adding the following to your test class:

@Override
protected PactSpecVersion getSpecificationVersion() {
    return PactSpecVersion.V2;
}