Search code examples
pactpact-jvm

stringType matcher in V3.0 contract for AMQ message does a literal match instead of type-matching


I have a contract that uses stringType to match a filename. The contract also specifies the matcher on type, but when I run the test on the provider side, it does a literal match. I've included the contract, the JSON that is send and a screenshot while debugging. I noticed that a TypeMatcher is initialized in the MatchingRuleGroup, but it has no fields. I'm not sure if this is correct

I tried 3 scenario's:

  • stringValue("bestandsid","20190219_foo_20190124.txt") --> this works

  • stringType("bestandsid","20190101_foo_20190124.txt") --> doesn't work, because it literally expects 20190101_foo_20190124.txt but got 20190219_foo_20190124.txt

  • stringType("bestandsid") --> doesn't work. It literally expects 'string' but got 20190219_foo_20190124.txt

At the provider I use

pact-jvm-provider-spring_2.12 - Version 3.6.2

At the consumer I use

pact-jvm-consumer-junit_2.12 - Version 3.6.2

pact-jvm-consumer-java8_2.12 - Version 3.6.2

CONTRACT:

{
    "consumer": {
        "name": "Consumer-event"
    },
    "provider": {
        "name": "Provider"
    },
    "messages": [
        {
            "description": "A message notifying a newly available foo file",
            "metaData": {
                "bestandstype": "foo",
                "Content-Type": "application/json"
            },
            "contents": {
                "headers": {
                    "bestandstype": "foo",
                    "Content-Type": "application/json"
                },
                "payload": {
                    "bestandstype": "foo",
                    "bestandsid": "string"
                }
            },
            "providerStates": [
                {
                    "name": "A new FOO file is extracted"
                }
            ],
            "matchingRules": {
                "body": {
                    "$.payload$.bestandsid": {
                        "matchers": [
                            {
                                "match": "type"
                            }
                        ],
                        "combine": "AND"
                    }
                }
            }
        }
    ],
    "metadata": {
        "pactSpecification": {
            "version": "3.0.0"
        },
        "pact-jvm": {
            "version": "3.6.2"
        }
    }
}

ACTUAL EVENT

{
    "headers": {
        "Content-Type": "application/json",
        "bestandstype": "foo",
        "id": "6838a619-efb7-6867-28bc-eb24609aa980",
        "timestamp": 1560410882485
    },
    "payload": {
        "afleidDatum": null,
        "bestandsid": "20190219_foo_20190124.txt",
        "bestandstype": "foo",
        "bron": null,
        "planDatum": null,
        "planType": "BAR"
    }
}

CONSUMER CONTRACT

    @Pact(provider = "DonnaFileshareReader", consumer = "DpcAdapter-event")
    public MessagePact eventNewDpcResource(MessagePactBuilder builder) {

        Map<String, String> metadata = new HashMap<>();
        metadata.put("Content-Type", "application/json");
        metadata.put("bestandstype", "dpc");

        PactDslJsonBody body = new PactDslJsonBody();
        body.object("headers")
            .stringValue("bestandstype", "dpc")
            .stringValue("Content-Type", "application/json")
            .closeObject();
        payload = new PactDslJsonBody();
        payload.stringValue("bestandstype", "dpc")
               .stringValue("bestandsid", EXAMPLE_DPC_FILE_NAME)
               .closeObject();
        body.object("payload", payload);

        return builder.given("A new DPC file is extracted")
                      .expectsToReceive("A message notifying a newly available dpc file")
                      .withMetadata(metadata)
                      .withContent(body)
                      .toPact();
    }

ERROR:


Verifying a pact between DpcAdapter-event and DonnaFileshareReader
  Given A new FOO file is extracted
  A message notifying a newly available foo file
2019-06-13 09:56:54.144  INFO [bar,,,] 7427 --- [           main] org.reflections.Reflections              : Reflections took 9011 ms to scan 388 urls, producing 275 keys and 35566 values 
    generates a message which
      has a matching body (FAILED)
      has matching metadata (OK)

Failures:

0) A message notifying a newly available foo file generates a message which has a matching body
      $.payload.bestandsid -> Expected 'string' but received '20190219_foo_20190124.txt'

DEBUG Debugging

I expect that stringType matches on the String type.


Solution

  • Solved.

    By changing the contract to 1 PactDslJsonBody() instead of using body(object,payload).

    New contract:

    body.object("headers")
                    .stringValue("bestandstype", "foo")
                    .stringValue("Content-Type", "application/json")
                    .closeObject();
            body.object("payload")
                    .stringValue("bestandstype", "foo")
                    .stringType("bestandsid", EXAMPLE_FOO_FILE_NAME)
                    .closeObject();
    

    New message construction in the test (although you can also construct the PactDslJsonBody as in the original question and use that)

            JSONObject resourceDetail = (JSONObject)body.getBody();
            JSONObject payload = resourceDetail.getJSONObject("payload");
    
            Message<byte[]> pactMessage = MessageBuilder
                    .withPayload(payload.toString().getBytes())
                    .copyHeaders(messageProvider.getMetadata())
                    .build();