pact-foundation / pact-jvm

JVM version of Pact. Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.
https://docs.pact.io
Apache License 2.0
1.08k stars 479 forks source link

Error running gradle verification with V3 messege #185

Closed jojo46 closed 8 years ago

jojo46 commented 8 years ago

Hey, so I'm getting the following when trying to verify my pact consumer using the new gradle mechanism where it checks against a class in the test class path.

Verifying a pact between WorkflowListenertest and WorkflowEnginetest [Using file /home/jojo/workspace/workflowengine-micro/target/pacts/WorkflowListenertest-WorkflowEnginetest.json] Given executing a workflow with rabbitmq WARNING: State Change ignored as there is no stateChange URL execution payload Request Failed - No such property: request for class: au.com.dius.pact.model.v3.messaging.Message

Failures:

0) Verifying a pact between WorkflowListenertest and WorkflowEnginetest - execution payload Given executing a workflow with rabbitmq No such property: request for class: au.com.dius.pact.model.v3.messaging.Message

:pactVerify_WorkflowEnginetest FAILED

I outputted the test classpath and it seems correct (the java file is in classes/test)

Test classpath is:- file: "/home/jojo/workspace/workflowengine-micro/build/classes/test" file: "/home/jojo/workspace/workflowengine-micro/build/resources/test" file: "/home/jojo/workspace/workflowengine-micro/build/classes/main" file: "/home/jojo/workspace/workflowengine-micro/build/resources/main"

The consumer code is

@Rule
public MessagePactProviderRule mockProvider = new MessagePactProviderRule(this);

@Pact(provider = PROVIDER, consumer = CONSUMER)
public MessagePact createPact(MessagePactBuilder builder) {
    PactDslJsonBody body = new PactDslJsonBody()
            .uuid("workflowId")
            .stringType("domain")
            .eachLike("values")
                .stringType("key")
                .stringType("value")
                .closeObject()
            .closeArray()
            .asBody();

    Map<String, String> metaData = new HashMap<>();
    metaData.put("contentType", "application/json");

    return builder.given("executing a workflow with rabbitmq")
            .expectsToReceive("execution payload")
            .withContent(body)
            .withMetadata(metaData)

// .given("executing a workflow with kafka") // .expectsToReceive("execution payload") // .withContent(body) // .withMetadata(metaData)

            .toPact();
}

@Test
@PactVerification(PROVIDER)
public void test() throws Exception {
    Assert.assertNotNull(new String(currentMessage));
}

public void setMessage(byte[] messageContents) {
    currentMessage = messageContents;
}

private byte[] currentMessage;

And the provider code is

public class WorkflowListenerProviderTest { @PactVerifyProvider("execution payload") public String test() throws JsonProcessingException { ExecutePayload payload = new ExecutePayload(); payload.setDomainId(PactConstants.MOCK); payload.setWorkflowId(UUID.randomUUID().toString()); payload.setValues(Collections.singletonMap(PactConstants.MOCK, PactConstants.MOCK));

    ModelMapperConfig mapperConfig = new ModelMapperConfig();
    MapperFacade mapperFacade = mapperConfig.mapper();

    ObjectMapper objectMapper = new JacksonConfig().jacksonObjectMapper();

    return objectMapper.writeValueAsString(mapperFacade.map(payload, com.bettercloud.models.ExecutePayload.class));
}

}

Anyway, I'm at a loss. Not sure what's going on and unfortunately the error message I'm seeing isn't very clear to me as to what it's asking for.

uglyog commented 8 years ago

The issue is it is treating the pact as a request/response and not a message pact (hence the 'No such property: request').

You may need to force it as it is not detecting it correctly. Add a verificationType = 'ANNOTATED_METHOD' in the consumer configuration hasPactWith block.


pact {

    serviceProviders {

        messageProvider {

            hasPactWith('messageConsumer') {
                pactFile = url('url/to/messagepact.json')
                verificationType = 'ANNOTATED_METHOD' // <-- add it here
            }

        }

    }

}
jojo46 commented 8 years ago

Ok, so some new issues. Though just an fyi but your documenation currently says to put that verificationType in the wrong place, imagine you'll cause a lot of frustration w/ that one :S

Here's the new output

Verifying a pact between WorkflowListenertest and WorkflowEnginetest [Using file /home/jojo/workspace/workflowengine-micro/target/pacts/WorkflowListenertest-WorkflowEnginetest.json] Given executing a workflow with rabbitmq WARNING: State Change ignored as there is no stateChange URL execution payload generates a message which Path expression .domainId is invalid, ignoring: [1.1] failure: $' expected but.' found

.domainId ^ Path expression .workflowId is invalid, ignoring: [1.1] failure: $' expected but.' found

.workflowId ^ Path expression .values[*].value is invalid, ignoring: [1.1] failure: $' expected but.' found

.values[].value ^ Path expression .values[].key is invalid, ignoring: [1.1] failure: $' expected but.' found

.values[*].key ^ Path expression .values is invalid, ignoring: [1.1] failure: $' expected but.' found

.values ^ Path expression .domainId is invalid, ignoring: [1.1] failure: $' expected but.' found

.domainId ^ Path expression .workflowId is invalid, ignoring: [1.1] failure: $' expected but.' found

.workflowId ^ Path expression .values[*].value is invalid, ignoring: [1.1] failure: $' expected but.' found

.values[].value ^ Path expression .values[].key is invalid, ignoring: [1.1] failure: $' expected but.' found

.values[*].key ^ Path expression .values is invalid, ignoring: [1.1] failure: $' expected but.' found

.values ^ Path expression .domainId is invalid, ignoring: [1.1] failure: $' expected but.' found

.domainId ^ Path expression .workflowId is invalid, ignoring: [1.1] failure: $' expected but.' found

.workflowId ^ Path expression .values[*].value is invalid, ignoring: [1.1] failure: $' expected but.' found

.values[].value ^ Path expression .values[].key is invalid, ignoring: [1.1] failure: $' expected but.' found

.values[*].key ^ Path expression .values is invalid, ignoring: [1.1] failure: $' expected but.' found

.values ^ Path expression .domainId is invalid, ignoring: [1.1] failure: $' expected but.' found

.domainId ^ Path expression .workflowId is invalid, ignoring: [1.1] failure: $' expected but.' found

.workflowId ^ Path expression .values[*].value is invalid, ignoring: [1.1] failure: $' expected but.' found

.values[].value ^ Path expression .values[].key is invalid, ignoring: [1.1] failure: $' expected but.' found

.values[*].key ^ Path expression .values is invalid, ignoring: [1.1] failure: $' expected but.' found

.values ^ Path expression .domainId is invalid, ignoring: [1.1] failure: $' expected but.' found

.domainId ^ Path expression .workflowId is invalid, ignoring: [1.1] failure: $' expected but.' found

.workflowId ^ Path expression .values[*].value is invalid, ignoring: [1.1] failure: $' expected but.' found

.values[].value ^ Path expression .values[].key is invalid, ignoring: [1.1] failure: $' expected but.' found

.values[*].key ^ Path expression .values is invalid, ignoring: [1.1] failure: $' expected but.' found

.values ^ has a matching body (FAILED)

Failures:

0) Verifying a pact between WorkflowListenertest and WorkflowEnginetest - execution payload Given executing a workflow with rabbitmq generates a message which has a matching body $.body.domainId -> Expected 'fGhtejKVHNaKdQQTZFZP' but received 'mock' $.body.values.0.key -> Expected 'OllExaYMteWSwchuWuHh' but received 'mock' $.body.values.0.value -> Expected 'fGDgUXXKwtLpAdMPLLyY' but received 'mock' $.body.workflowId -> Expected '79b1b9c3-100b-4b34-bd25-b0098c06d451' but received '509b7362-517a-4a44-9f2e-1d195f25a774'

  Diff:

  @1
  -    "domainId": "fGhtejKVHNaKdQQTZFZP",
  +    "domainId": "mock",
      "values": [

  @4
          {
  -            "key": "OllExaYMteWSwchuWuHh",
  -            "value": "fGDgUXXKwtLpAdMPLLyY"
  +            "key": "mock",
  +            "value": "mock"
          }

  @8
      ],
  -    "workflowId": "79b1b9c3-100b-4b34-bd25-b0098c06d451"
  +    "workflowId": "509b7362-517a-4a44-9f2e-1d195f25a774"
  }

:pactVerify_WorkflowEnginetest FAILED

FAILURE: Build failed with an exception.

BUILD FAILED

Total time: 19.405 secs

The json created by the consumer is

{ "consumer": { "name": "WorkflowListenertest" }, "provider": { "name": "WorkflowEnginetest" }, "messages": [ { "metaData": { "contentType": "application/json" }, "providerState": "executing a workflow with rabbitmq", "contentType": "application/json", "contents": { "domainId": "fGhtejKVHNaKdQQTZFZP", "values": [ { "key": "OllExaYMteWSwchuWuHh", "value": "fGDgUXXKwtLpAdMPLLyY" } ], "workflowId": "79b1b9c3-100b-4b34-bd25-b0098c06d451" }, "matchingRules": { ".domainId": { "match": "type" }, ".values": { "min": 0, "match": "type" }, ".values[].value": { "match": "type" }, ".workflowId": { "regex": "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" }, ".values[].key": { "match": "type" } }, "description": "execution payload" } ], "metadata": { "pact-specification": { "version": "3.0.0" }, "pact-jvm": { "version": "3.1.3" } } }

As you can see, the matching should simply be as "string" type, not an actual value specific matcher. I'm guessing all the "xxx is invalid" messages above that are from it trying to do a value match and finding they aren't matched.

uglyog commented 8 years ago

Actually, in this case the documentation is correct. Putting the verificationType there is a work around.

For some reason, there matcher paths are incorrect (they are missing the $.body prefix and hence the type matching is not working). Here is the corrected pact:

{
  "consumer": {
    "name": "WorkflowListenertest"
  },
  "provider": {
    "name": "WorkflowEnginetest"
  },
  "messages": [
    {
      "metaData": {
        "contentType": "application/json"
      },
      "providerState": "executing a workflow with rabbitmq",
      "contentType": "application/json",
      "contents": {
        "domainId": "fGhtejKVHNaKdQQTZFZP",
        "values": [
          {
            "key": "OllExaYMteWSwchuWuHh",
            "value": "fGDgUXXKwtLpAdMPLLyY"
          }
        ],
        "workflowId": "79b1b9c3-100b-4b34-bd25-b0098c06d451"
      },
      "matchingRules": {
        "$.body.domainId": {
          "match": "type"
        },
        "$.body.values": {
          "min": 0,
          "match": "type"
        },
        "$.body.values[*].value": {
          "match": "type"
        },
        "$.body.workflowId": {
          "regex": "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
        },
        "$.body.values[*].key": {
          "match": "type"
        }
      },
      "description": "execution payload"
    }
  ],
  "metadata": {
    "pact-specification": {
      "version": "3.0.0"
    },
    "pact-jvm": {
      "version": "3.1.3"
    }
  }
}

I'll look into why the paths are not being correctly constructed.

jojo46 commented 8 years ago

Cool, I would be curious to know why the correct place didn't work. Really just curiosity so if you're not sure then all good, there's a workaround so I'm happy.

And the change worked, though obviously I can't really fix the pacts manually as the plan is to upload these to a pact broker at some point.

Anyway, certainly appreciate the help, let me know if/when you figure out what's up with the incorrect rule formatting and we'll update our gradle dependency to meet the new fixed version :)

Thanks much man, beyond appreciate the quick turnaround. Don't think I've ever seen anyone respond so fast so really, very very appreciated to say the least :)

uglyog commented 8 years ago

More than happy to help.

My suspicion is that a default is being applied at the consumer level which is resetting the verificationType. So the work around just reset it back.

jojo46 commented 8 years ago

Btw, do you have an estimate for when you think you'll be able to fix the prefix issue with the matching rules uglyog?

uglyog commented 8 years ago

Sorry, I'm unable to give an estimate. I would have to investigate the issue first.

uglyog commented 8 years ago

Looks like a simple fix, should have it done today.

jojo46 commented 8 years ago

Awesome, is this updated in maven as well? Thank you for doing this so fast Ron!

uglyog commented 8 years ago

The matcher keys will be fixed in the maven plugin as well. I need to double check how the verification type is being set.