pact-foundation / pact-net

.NET 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://pact.io
MIT License
847 stars 232 forks source link

Generated ID as part of the path #52

Closed jtsoftwaredevelopment closed 9 years ago

jtsoftwaredevelopment commented 9 years ago

Hi,

I'm trying to build pacts that have randomly generated unique IDs in the path. Example:

  "request": {
    "method": "get",
    "path": "/groups/d6a61741-203a-4b8a-aec1-c9db15cff87b/messages/8a975ddf-1786-48a8-b835-8f7f578afbf1/locations",
    "headers": {
      "Accept": "application/json"
    }
  },

Is this possible to do this using PactNet? Does it matter that it is Pact 1.1 Specification - am I required to use Pact 2 Specification compatible tools/platforms for regular expressions to be part of the path? Or is it the case that the "path" can never be this dynamic, regardless of the Pact Specification version?

Thanks a bunch. -Jon

neilcampbell commented 9 years ago

Hi @jtsoftwaredevelopment Thanks for getting in touch.

This is supported and we have an example of this in the sample project (see https://github.com/SEEK-Jobs/pact-net/blob/master/Samples/EventApi/Consumer.Tests/EventsApiConsumerTests.cs#L218). This can be a little tricky however as your http client will need to support generating the deterministic random id's in your test case (if they aren't passed in).

Depending on your use case, you may also need to specify a given state (provider state) on the consumer side and then on the provider verification side you will need to supply an action that will setup the correct state so the verification passes.

jtsoftwaredevelopment commented 9 years ago

Thanks for the quick response.

The issue is that I cannot hard-code my GUID values into the pact, as in that example, because my provider does not allow me to create resources of a particular GUID. That's what I meant by the word 'random'. Sorry for any confusion.

As I understand it, for my response body to include (variable) DateTime and GUID types of data, because cannot be deterministic values on the provider side, I will need to wait for the Spec 2 implementation for regex matching. Please correct me if I'm wrong on this.

However, my central question is about the dynamic path. Is there currently a way to override the path on the provider side? I had one thought on how to do this with string placeholders, but it feels like I'm probably going down the wrong path (see below). Is this valid, or is there any other possible way to reconstruct the path on the provider side? Thanks!

// In the test...
.Given("an existing group {0} has a message {1} with an existing location")

// In the pact ...
"request": {
  "method": "get",
  "path": "/groups/{0}/messages/{1}/locations",
  "headers": {
    "Accept": "application/json"
  }
  "body": {
    "foo": "bar"
  }
},
neilcampbell commented 9 years ago

Version 2 of the spec will have flexible matching on the request/response body, however not in the path.

Is the provider something that you do not control? If not, it is going to be very hard to get the provider into a predictable state. If you do, you should be able to inject mocks/stubs/fakes or use middleware in the correct place, such that you can generate a predictable state.

To answer your last paragraph, you can do whatever you like on the provider side. All Pact does is send the request and make sure the correct response is returned, so you could inject some OWIN middleware which does the things you need. There is also an override available on the ServiceProvider method, which takes a Func<ProviderServiceRequest, ProviderServiceResponse> as the second param and allows you to define your own HTTP client. Technically you can mutate the request here before sending it to the provider, however it is something I would do as a last resort.

jtsoftwaredevelopment commented 9 years ago

Hi Neil,

Thanks for your help on this. I was able to re-write the Pact on the provider side with the non-deterministic, provider-generated GUIDs appended to the path and provider state using string placeholders and JSON.NET. I'm only doing this because it doesn't seem like any of the Pact specifications take into account non-deterministic IDs in the path.

However, I'm looking forward to the V2 release of PactNet. The ability to regex match elements in the response body is currently a blocker for my organization in adopting the tool. I'm curious about any expected timeline for the release, but I don't want to sound pushy. If anything, I should be asking if there are features that you'd like me to implement and pull request. Feel free to get a hold of me directly if something comes to mind.

Thanks, -Jon

neilcampbell commented 9 years ago

Yeah, V2 of the spec is going to make the tool a lot more flexible. I can't really give any timeframes unfortunately, however you can keep track of the conversation here https://github.com/SEEK-Jobs/pact-net/issues/9

arun290636 commented 5 years ago

@jtsoftwaredevelopment any update on this issue ? I am facing same problem in my project.

mayank1004 commented 2 years ago

I am facing similar issue as well, any help would be appreciated! Thanks!