pact-foundation / pact-mock_service

Provides a mock service for use with Pact
https://pact.io
MIT License
72 stars 68 forks source link

Return most specific match when multiple matches are found #138

Open jstockwin opened 1 year ago

jstockwin commented 1 year ago

I have a contract for /endpoint, which returns a list of items. It's possible to apply filters in query params, e.g. /endpoint?type=foo, but this is optional.

Let's say I have three interactions:

  1. path: /endpoint (no query)
  2. path: /endpoint, query: type=foo
  3. path: /endpoint, query: type=bar

When running the stub server, if I make a request for /endpoint?type=foo the stub service matches both (1) and (2). It (correctly) does not match (3). It throws a warning about multiple matches, and says WARN -- : Sorting responses by response status and returning first.

I understand that we're trying to be permissive here - i.e. in the case that interaction (2) didn't exist, I'd see why you'd want to return (1) instead of 404/500. However, in the case that one match is more specific, it'd be nice to return this.

In my case, I'm getting the response from (1), which is returning all items instead of only items with type=foo. Then when trying to use the stub-service for integration testing, the filtering appears to not work.

I have tried explicitly setting query="" when running my unit tests (to make 1 more explicit), but this does not get saved into the contract file.

My current workaround is to put xxxx into my test name for the one with no query params. This means the test runs last, and so is the last entry in the contract json file, meaning the more specific one happens to get picked first.

rholshausen commented 1 year ago

Can you confirm the version you are using? I can't replicate this, it works correctly for me.

With a Pact file with those 3 interactions, I get:

❯ curl 'http://127.0.0.1:40957/endpoint'
{"response":1}
❯ curl 'http://127.0.0.1:40957/endpoint?type=foo'
{"response":2}
❯ curl 'http://127.0.0.1:40957/endpoint?type=bar'
{"response":3}
❯ curl -v 'http://127.0.0.1:40957/endpoint?type=x'
*   Trying 127.0.0.1:40957...
* Connected to 127.0.0.1 (127.0.0.1) port 40957 (#0)
> GET /endpoint?type=x HTTP/1.1
> Host: 127.0.0.1:40957
> User-Agent: curl/7.81.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< access-control-allow-origin: *
< content-length: 0
< date: Mon, 24 Oct 2022 05:17:05 GMT
< 
* Connection #0 to host 127.0.0.1 left intact
jstockwin commented 1 year ago

Hi @rholshausen, thanks for the response.

I've just created https://github.com/jstockwin/pact-issue-demo to demonstrate this issue.

If I curl http://localhost:8000/endpoint?type=bar there, I'm getting the (incorrect) response of {"type":"none"}.

The docker-logs.txt file shows the messages about multiple interactions matching.

I probably should have mentioned that I'm doing this through the pactfoundation/pact-cli:latest docker image. Am I in the wrong place?

Overriding the command there to run the version command of the CLI gives me 0.5.0. I don't seem to be able to do this for the stub-service command on it's own.

rholshausen commented 1 year ago

Ah! Yeah, that would need to be addressed with the pact-cli project. It is a different implementation.

rholshausen commented 1 year ago

I'll move this issue to that project