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

.datetime() changes pact and breaks pact spec V3 #1726

Closed huehnerlady closed 12 months ago

huehnerlady commented 1 year ago

Hi,

I am updating pact due to groovy and spring-boot 3 updates. We were at 4.1.34 and now we would like to go to 4.6.3

Unfortunately this breaks the pact.

We have our mochServer set up like this:

  @Pact(consumer = CONSUMER)
  RequestResponsePact get(PactDslWithProvider builder) {
    return builder
        .uponReceiving("Get ")
        .method("GET")
        .path("/foo")
        .willRespondWith()
        .status(200)
        .body(new PactDslJsonBody().datetime("lastResponse", ISO_8601_EXTENDED_DATETIME_FORMAT.getPattern(), parse("2022-03-18T09:23:54.00Z"), TimeZone.getTimeZone("UTC")))
        .toPact()
  }

before the change, this created a pact looking like this:

{
  "interactions": [
    {
      "response": {
        "matchingRules": {
          "body": {
            "$.lastResponse": {
              "combine": "AND",
              "matchers": [
                {
                  "timestamp": "yyyy-MM-dd'T'HH:mm:ss",
                  "match": "timestamp"
                }
              ]
            }
          }
        },
        "status": 200
      }
    }
  ]
}

When we now migrate to pact 4.6.3 and mark the test as V3, we get this:

{
  "interactions": [
    {
      "response": {
        "matchingRules": {
          "body": {
            "$.lastResponse": {
              "combine": "AND",
              "matchers": [
                {
                  "format": "yyyy-MM-dd'T'HH:mm:ss", <-----
                  "match": "timestamp"
                }
              ]
            }
          }
        },
        "status": 200
      }
    }
  ]
}

then we get the error in the provider:

1) Verifying a pact between <consumer> and <provider> - Get has a matching body

    1.1) body: $.lastResponse Expected "2021-05-10T16:40:55" to match a datetime of 'yyyy-MM-dd HH:mm:ssZZZZZ': Unable to parse the date: 2021-05-10T16:40:55

do you have a tip, how we can get the pact json set timestamp instead of format?

YOU54F commented 1 year ago

i'm not sure and would need to create an example, are you able to produce a reproducible test case, for example a repo with two branches one pre and post upgrade

rholshausen commented 1 year ago

how we can get the pact json set timestamp instead of format

timestamp attribute is deprecated. It will use either, but format is preferred.

Your date/time values do not have timezones. Try removing the timezone value (the fourth parameter to datetime)

huehnerlady commented 1 year ago

how we can get the pact json set timestamp instead of format

timestamp attribute is deprecated. It will use either, but format is preferred.

Your date/time values do not have timezones. Try removing the timezone value (the fourth parameter to datetime)

@rholshausen thanks for your answer. unfortunately these changes did not help, I can only make the producer test green by using timestamp instead of format.

So does that mean in the higher version even the V3 spec changes?

YOU54F commented 1 year ago

What version is your provider running? If your provider is updated to the same version as the consumer, does that solve it? Appreciate it that is more effort and co-ordination that you would want? Just curious.

As said it is possible to create a simple repro which matches your setup, I'd be more than happy to take a look. Ron is our pact-jvm expert, and is based in Aus, so that repro would probably help us, with async support otherwise it might be a fair bit of back and forth!

huehnerlady commented 1 year ago

What version is your provider running? If your provider is updated to the same version as the consumer, does that solve it? Appreciate it that is more effort and co-ordination that you would want? Just curious.

Hi, the problem is that the update is not in our hands as it is a different department, I will have a look into that. I was assuming that if you support V3 of the pact, there is no dependency update that suddenly changes the json? Is my assumtion wrong then?

As said it is possible to create a simple repro which matches your setup, I'd be more than happy to take a look. Ron is our pact-jvm expert, and is based in Aus, so that repro would probably help us, with async support otherwise it might be a fair bit of back and forth!

I am working on the example, however I now run into a completely different issue which I try to solve at the moment 😅

huehnerlady commented 1 year ago

I started to create a sample project here, however something is still missing as it has a weird error message. Theoretically the pact from consumer-working-pact-contracttests needs to work. I will have a further look but maybe you have an idea what the problem is there

YOU54F commented 1 year ago

Thanks for the example, I will endeavour to take a look today.

I was assuming that if you support V3 of the pact, there is no dependency update that suddenly changes the json? Is my assumtion wrong then?

That would have been my assumption for each spec version - that between versions of pact libraries that support a spec version such as V3, there should be no changes to the Pact file (save for where the client library has incorrectly implemented something that didn't adhere to the spec).

However this thread sheds a bit more light on how matchers/generators are strictly not part of the spec, and matchers/generators are designed as extension points.

https://github.com/pact-foundation/pact-specification/issues/95#issuecomment-1156062360

Pact-JVM actually uses it's own core implementation of the Pact specification, whereas the other libraries where I am more familiar either traditionally relied on a Ruby core, and now have migrated to a Rust core.

From viewing the Pact-JVM libraries and studying users behaviours, I can see a combinatory explosion of packages, and versions depending on kotlin/maven/gradle and the java versions themselves, which I why I usually ask for a set of demo repos to play around with (as I am really not sure what your path forward is at the moment, so it would be a case of experimentation from my side).

Appreciate that doesn't help you much at the moment, and for this point

Hi, the problem is that the update is not in our hands as it is a different department

This might be tricky, I don't have a simple answer at the moment, but once we can get the consumer/provider pact creation/verification in sync, we can work out if its a library issue or not.

Also lastly, whilst this is probably a less than ideal solution, for the moment, you could manually update that key in a pact file, prior to upload, to decouple yourself from the provider update on their side. (if it is indeed a lib update that solves it on the provider side)

YOU54F commented 1 year ago

I'd also have a look at the changelogs from these versions

4.1.34 -> 4.6.3 to see if there is anything stand-out, relating to your issue, as it provides me a reference point as to what the code is actually doing pre and post issue

YOU54F commented 1 year ago

Hey taking a look at the demo now.

Just trying to work out which versions of Java you are using.

https://github.com/pact-foundation/pact-jvm/?tab=readme-ov-file#supported-jdk-and-specification-versons

4.1.x supports 8-12 of the jdk 4.6.x is jdk 17+

I was running 17 yesterday so will switch to diff version and try again. maybe I'm not running the right command ./gradlew consumer-working-pact-contracttests:tasks test to generate the consumer pacts

YOU54F commented 1 year ago

ok so its setup to use java 17 and I've got it generating pacts against v4.1.34 so will update to v4.6.3 - check the Pact and then can start playing around. Thanks for the demo repo 👍🏾

YOU54F commented 1 year ago

https://github.com/YOU54F/demo-pact-v3/commits/main/

Have been working from a fork. I can reproduce your issue, which occurs with a mismatch between pact versions 4.1.x & 4.6.x

If both consumer + provider are on the same version, verification is successful, otherwise with the consumer pact generated on 4.6.x results in a timestamp that can't be parsed error message using 4.2.x

    1) Verifying a pact between Consumer-Working and provider - consumer-test has a matching body

        1.1) body: $.lastResponse Expected "2023-11-10T14:03:53" to match a datetime of 'yyyy-MM-dd HH:mm:ssZZZZZ': Unable to parse the date: 2023-11-10T14:03:53
        at au.com.dius.pact.provider.junit5.PactVerificationContext.verifyInteraction(PactVerificationContext.kt:63)
        at de.huehnerlady.demo.provider.ProviderPactTest.pactVerificationTestTemplate(ProviderPactTest.java:35)

I wouldn't be expecting this error to be coming from Pact Unable to parse the date: 2023-11-10T14:03:53

It might be a bug, I would have to go source digging.

As a workaround, to allow you to update your consumer, whilst not updating the provider, would be to modify the pact contract prior to upload. This might be a preferable option, as the provider team is out of your control

The provider on 4.2.6 and 4.6.3 can deal with the Pact file generated from 4.1.34. 4.2.6 will failed to deal with the Pact generated from 4.6.3 consumer.

This means that even with the workaround in place from the consumer side to modify, the provider team wouldn't see any issues, when they do decide to update to a later Pact client version.

huehnerlady commented 1 year ago

@YOU54F thank you so much for your help, I will try that next week and also consult with our provider team what the best approach is.

What I do understand is that the pact version is also not set in stone. So pact V3 with version 4.6.3 is different from pact V3 with version 4.1.34, because the library might change the way to generate the pact json. Is that correct?

rholshausen commented 12 months ago

You should upgrade your provider project to 4.6.x first, and when that is working, upgrade the consumer project.

huehnerlady commented 12 months ago

Yes, so I am now in the discussions with our Provider team to see what we can do. Hopefully the upgrade is working out fine on their side.

Thanks for the clarification around the pactSpec not being set in stone when upgrading to a higher pact-jvm version and all the other help ❤️