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

Matching rule for non-empty map or a field which is not null #727

Open QMG-kazala opened 6 years ago

QMG-kazala commented 6 years ago

My problem is I have a field which is a list (an array) of maps. Each map can have elements of different types (strings or sub-maps), eg.

"validatedAnswers": [
    {
      "type": "typeA",
      "answers": {
        "favourite_colour": "Blue",
        "correspondence_address": {
            "line_1": "Main St",
            "postcode": "1A 2BC",
            "town": "London"
        }
      }
    },
    {
      "type": "typeB",
      "answers": {
        "first_name": "Firstname",
        "last_name": "Lastname",
      }
    }
  ]

and we're only interested in some of those answers.

What we really need is this: https://github.com/pact-foundation/pact-specification/issues/38, but it's planned for v.4. In the meantime we're trying a different approach. What I'm attempting to do now is to specify that each element of the list is a non-empty map. Another approach is to specify that each element of the list is not null. Can any of this be done using Groovy DSL?

This:

validatedAnswers minLike(1) {
     type string()
     answers {
     }
}

doesn't work because it mean answers is expected to be empty ("Expected an empty Map but received Map( [...] )", see also https://github.com/DiUS/pact-jvm/issues/298).

So what I would like to do is something like this:

.withBody {
    validatedAnswers minLike(1) {
         type string()
         answers Matchers.map()
    }
}

or:

validatedAnswers minLike(1) {
     type string()
     answers {
             keyLike 'title', notNull()
     }
}

or:

validatedAnswers minLike(1) {
     type string()
     answers notNull()
}

Can it be done?

QMG-kazala commented 6 years ago

Anyone? Anything? Is there a chance notNull() matcher (or map() or anything similar) will be added in the future?

uglyog commented 6 years ago

This is impossible to support with the current implementation. The behaviour is to apply the matchers at the attribute level, and you can't apply them conditionally based on a predicate.

What we need to be able to apply a set of matchers based on a predicate:

validatedAnswers minLike(1) {
  when(type == "typeA") {
    favourite_colour string()
    ...
  }
}

But this will not be possible to implement without a change to the specification.

QMG-kazala commented 6 years ago

Oh yes!!!! Having predicate-based matchers would solve so many problems! It would be great :D 👍 Does it mean it's planned for version 4?

uglyog commented 6 years ago

Yes it will have to be a V4 change because it will require a change to the pact file format as well as how the matchers are applied.

alexfdz commented 4 years ago

@uglyog will this be included in V4?

uglyog commented 4 years ago

@alexfdz we are going to look at having sets of matching rules applied to different objects in lists. https://github.com/pact-foundation/pact-specification/issues/38 will track this.