Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[V3] Mock server fails with mismatches when using fromProviderState in iterated interaction #604

Open
saw-jan opened this issue Feb 10, 2021 · 6 comments
Labels
bug Indicates an unexpected problem or unintended behavior upstream Indicates that an issue relates to an upstream problem (such as in pact-reference)

Comments

@saw-jan
Copy link

saw-jan commented Feb 10, 2021

We tried to implement fromProviderState in an interaction that is iterated in the test (see code below) but running consumer test fails with;

Error: Mock server failed with the following mismatches: 

      1) The following request was expected but not received: 
          Method: GET
          Path: /users
          Query String: id=2
          Headers:
            Accept: application/hal+json
            Authorization: Basic YWRtaW46YWRtaW4=

      2) The following request was expected but not received: 
          Method: GET
          Path: /users
          Query String: id=3
          Headers:
            Accept: application/hal+json
            Authorization: Basic YWRtaW46YWRtaW4=

From above , it seems that interaction with id 1 gets passed

Note: All interactions pass with other Matchers except fromProviderState

Code:

  // interaction
  const aGETUserInfoByIdQueryInteraction = (provider, id, username, email) => {
    return provider
      .given('user is created', { username, email })
      .uponReceiving('a GET request for user by id as query ' + id)
      .withRequest({
        method: 'GET',
        path: '/users',
        query: { id: MatchersV3.fromProviderState('\${id}', id.toString()) },
        headers: {
          ...client.basicAuth,
          Accept: 'application/hal+json',
        },
      })
      .willRespondWith({
        status: 200,
        headers: {
          'content-type': 'application/hal+json',
        },
        body: {
          id: MatchersV3.number(id),
          username: MatchersV3.string(username),
          email: MatchersV3.string(email),
        },
      });
  };
  
  // test
  it('using in a loop: "fromProviderState" as query', async () => {
    for (let user of users) {
      aGETUserInfoByIdQueryInteraction(
        provider,
        user.id,
        user.username,
        user.email
      );
    }
    return provider.executeTest(async () => {
      for (let user of users) {
        await client.getUserByIdQuery(user.id);
      }
    });
  });

LOG:

[2021-02-10T07:16:52Z DEBUG pact_js_v3] Initialising Pact native library version 0.0.6
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Request = Request ( method: GET, path: /users, query: Some({"id": ["1"]}), headers: Some({"Authorization": ["Basic YWRtaW46YWRtaW4="], "Accept": ["application/hal+json"]}), body: Missing )
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Request matching rules = MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Request generators = Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Response = Response ( status: 200, headers: Some({"content-type": ["application/hal+json"]}), body: Present(50 bytes, application/json) )
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Response matching rules = MatchingRules { rules: {"body": MatchingRuleCategory { name: "body", rules: {"$.email": RuleList { rules: [Type], rule_logic: And }, "$.username": RuleList { rules: [Type], rule_logic: And }, "$.id": RuleList { rules: [Number], rule_logic: And }} }} }
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Response generators = Generators { categories: {} }
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Request = Request ( method: GET, path: /users, query: Some({"id": ["2"]}), headers: Some({"Authorization": ["Basic YWRtaW46YWRtaW4="], "Accept": ["application/hal+json"]}), body: Missing )
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Request matching rules = MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Request generators = Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Response = Response ( status: 200, headers: Some({"content-type": ["application/hal+json"]}), body: Present(48 bytes, application/json) )
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Response matching rules = MatchingRules { rules: {"body": MatchingRuleCategory { name: "body", rules: {"$.id": RuleList { rules: [Number], rule_logic: And }, "$.username": RuleList { rules: [Type], rule_logic: And }, "$.email": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Response generators = Generators { categories: {} }
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Request = Request ( method: GET, path: /users, query: Some({"id": ["3"]}), headers: Some({"Accept": ["application/hal+json"], "Authorization": ["Basic YWRtaW46YWRtaW4="]}), body: Missing )
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Request matching rules = MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Request generators = Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Response = Response ( status: 200, headers: Some({"content-type": ["application/hal+json"]}), body: Present(50 bytes, application/json) )
[2021-02-10T07:16:52Z DEBUG pact_js_v3] Response matching rules = MatchingRules { rules: {"body": MatchingRuleCategory { name: "body", rules: {"$.id": RuleList { rules: [Number], rule_logic: And }, "$.username": RuleList { rules: [Type], rule_logic: And }, "$.email": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T07:16:52.522Z] DEBUG: pact@10.0.0-beta.30/72236 on JT101: Initialised native library 0.0.6

 RUNS  tests/pactV3.test.js
[2021-02-10T07:16:52Z DEBUG pact_mock_server::hyper_server] Creating pact request from hyper request
[2021-02-10T07:16:52Z INFO  pact_mock_server::hyper_server] Received request Request ( method: GET, path: /users, query: Some({"id": ["1"]}), headers: Some({"accept": ["application/hal+json"], "user-agent": ["axios/0.21.1"], "connection": ["close"], "host": ["127.0.0.1:1234"], "authorization": ["Basic YWRtaW46YWRtaW4="]}), body: Empty )
[2021-02-10T07:16:52Z INFO  pact_matching] comparing to expected Request ( method: GET, path: /users, query: Some({"id": ["1"]}), headers: Some({"Authorization": ["Basic YWRtaW46YWRtaW4="], "Accept": ["application/hal+json"]}), body: Missing )
[2021-02-10T07:16:52Z DEBUG pact_matching]      body: ''
[2021-02-10T07:16:52Z DEBUG pact_matching]      matching_rules: MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T07:16:52Z DEBUG pact_matching]      generators: Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '/users' to '/users' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] expected content type = '*/*', actual content type = '*/*'
[2021-02-10T07:16:52Z DEBUG pact_matching] content type header matcher = 'None'
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '1' to '1' using Type
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing 'Basic YWRtaW46YWRtaW4=' to 'Basic YWRtaW46YWRtaW4=' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] --> Mismatches: []
[2021-02-10T07:16:52Z INFO  pact_matching] comparing to expected Request ( method: GET, path: /users, query: Some({"id": ["2"]}), headers: Some({"Authorization": ["Basic YWRtaW46YWRtaW4="], "Accept": ["application/hal+json"]}), body: Missing )
[2021-02-10T07:16:52Z DEBUG pact_matching]      body: ''
[2021-02-10T07:16:52Z DEBUG pact_matching]      matching_rules: MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T07:16:52Z DEBUG pact_matching]      generators: Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '/users' to '/users' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] expected content type = '*/*', actual content type = '*/*'
[2021-02-10T07:16:52Z DEBUG pact_matching] content type header matcher = 'None'
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '2' to '1' using Type
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing 'Basic YWRtaW46YWRtaW4=' to 'Basic YWRtaW46YWRtaW4=' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] --> Mismatches: []
[2021-02-10T07:16:52Z INFO  pact_matching] comparing to expected Request ( method: GET, path: /users, query: Some({"id": ["3"]}), headers: Some({"Accept": ["application/hal+json"], "Authorization": ["Basic YWRtaW46YWRtaW4="]}), body: Missing )
[2021-02-10T07:16:52Z DEBUG pact_matching]      body: ''
[2021-02-10T07:16:52Z DEBUG pact_matching]      matching_rules: MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T07:16:52Z DEBUG pact_matching]      generators: Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '/users' to '/users' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] expected content type = '*/*', actual content type = '*/*'
[2021-02-10T07:16:52Z DEBUG pact_matching] content type header matcher = 'None'
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '3' to '1' using Type
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing 'Basic YWRtaW46YWRtaW4=' to 'Basic YWRtaW46YWRtaW4=' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] --> Mismatches: []
[2021-02-10T07:16:52Z DEBUG pact_mock_server::hyper_server] Test context = {"mockServer": Object({"href": String("http://127.0.0.1:1234"), "port": Number(1234)})}
[2021-02-10T07:16:52Z INFO  pact_mock_server::hyper_server] Request matched, sending response Response ( status: 200, headers: Some({"content-type": ["application/hal+json"]}), body: Present(50 bytes, application/json) )
[2021-02-10T07:16:52Z DEBUG pact_mock_server::hyper_server]      body: '{"email":"adam@mail.com","id":1,"username":"Adam"}'
[2021-02-10T07:16:52Z DEBUG pact_mock_server::hyper_server] Creating pact request from hyper request
[2021-02-10T07:16:52Z INFO  pact_mock_server::hyper_server] Received request Request ( method: GET, path: /users, query: Some({"id": ["2"]}), headers: Some({"accept": ["application/hal+json"], "authorization": ["Basic YWRtaW46YWRtaW4="], "connection": ["close"], "host": ["127.0.0.1:1234"], "user-agent": ["axios/0.21.1"]}), body: Empty )
[2021-02-10T07:16:52Z INFO  pact_matching] comparing to expected Request ( method: GET, path: /users, query: Some({"id": ["1"]}), headers: Some({"Authorization": ["Basic YWRtaW46YWRtaW4="], "Accept": ["application/hal+json"]}), body: Missing )
[2021-02-10T07:16:52Z DEBUG pact_matching]      body: ''
[2021-02-10T07:16:52Z DEBUG pact_matching]      matching_rules: MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T07:16:52Z DEBUG pact_matching]      generators: Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '/users' to '/users' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] expected content type = '*/*', actual content type = '*/*'
[2021-02-10T07:16:52Z DEBUG pact_matching] content type header matcher = 'None'
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '1' to '2' using Type
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing 'Basic YWRtaW46YWRtaW4=' to 'Basic YWRtaW46YWRtaW4=' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] --> Mismatches: []
[2021-02-10T07:16:52Z INFO  pact_matching] comparing to expected Request ( method: GET, path: /users, query: Some({"id": ["2"]}), headers: Some({"Authorization": ["Basic YWRtaW46YWRtaW4="], "Accept": ["application/hal+json"]}), body: Missing )
[2021-02-10T07:16:52Z DEBUG pact_matching]      body: ''
[2021-02-10T07:16:52Z DEBUG pact_matching]      matching_rules: MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T07:16:52Z DEBUG pact_matching]      generators: Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '/users' to '/users' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] expected content type = '*/*', actual content type = '*/*'
[2021-02-10T07:16:52Z DEBUG pact_matching] content type header matcher = 'None'
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '2' to '2' using Type
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing 'Basic YWRtaW46YWRtaW4=' to 'Basic YWRtaW46YWRtaW4=' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] --> Mismatches: []
[2021-02-10T07:16:52Z INFO  pact_matching] comparing to expected Request ( method: GET, path: /users, query: Some({"id": ["3"]}), headers: Some({"Accept": ["application/hal+json"], "Authorization": ["Basic YWRtaW46YWRtaW4="]}), body: Missing )
[2021-02-10T07:16:52Z DEBUG pact_matching]      body: ''
[2021-02-10T07:16:52Z DEBUG pact_matching]      matching_rules: MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T07:16:52Z DEBUG pact_matching]      generators: Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '/users' to '/users' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] expected content type = '*/*', actual content type = '*/*'
[2021-02-10T07:16:52Z DEBUG pact_matching] content type header matcher = 'None'
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '3' to '2' using Type
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing 'Basic YWRtaW46YWRtaW4=' to 'Basic YWRtaW46YWRtaW4=' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] --> Mismatches: []
[2021-02-10T07:16:52Z DEBUG pact_mock_server::hyper_server] Test context = {"mockServer": Object({"href": String("http://127.0.0.1:1234"), "port": Number(1234)})}
[2021-02-10T07:16:52Z INFO  pact_mock_server::hyper_server] Request matched, sending response Response ( status: 200, headers: Some({"content-type": ["application/hal+json"]}), body: Present(50 bytes, application/json) )
[2021-02-10T07:16:52Z DEBUG pact_mock_server::hyper_server]      body: '{"email":"adam@mail.com","id":1,"username":"Adam"}'
[2021-02-10T07:16:52Z DEBUG pact_mock_server::hyper_server] Creating pact request from hyper request
[2021-02-10T07:16:52Z INFO  pact_mock_server::hyper_server] Received request Request ( method: GET, path: /users, query: Some({"id": ["3"]}), headers: Some({"connection": ["close"], "host": ["127.0.0.1:1234"], "accept": ["application/hal+json"], "authorization": ["Basic YWRtaW46YWRtaW4="], "user-agent": ["axios/0.21.1"]}), body: Empty )
[2021-02-10T07:16:52Z INFO  pact_matching] comparing to expected Request ( method: GET, path: /users, query: Some({"id": ["1"]}), headers: Some({"Authorization": ["Basic YWRtaW46YWRtaW4="], "Accept": ["application/hal+json"]}), body: Missing )
[2021-02-10T07:16:52Z DEBUG pact_matching]      body: ''
[2021-02-10T07:16:52Z DEBUG pact_matching]      matching_rules: MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T07:16:52Z DEBUG pact_matching]      generators: Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '/users' to '/users' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] expected content type = '*/*', actual content type = '*/*'
[2021-02-10T07:16:52Z DEBUG pact_matching] content type header matcher = 'None'
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '1' to '3' using Type
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing 'Basic YWRtaW46YWRtaW4=' to 'Basic YWRtaW46YWRtaW4=' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] --> Mismatches: []
[2021-02-10T07:16:52Z INFO  pact_matching] comparing to expected Request ( method: GET, path: /users, query: Some({"id": ["2"]}), headers: Some({"Authorization": ["Basic YWRtaW46YWRtaW4="], "Accept": ["application/hal+json"]}), body: Missing )
[2021-02-10T07:16:52Z DEBUG pact_matching]      body: ''
[2021-02-10T07:16:52Z DEBUG pact_matching]      matching_rules: MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T07:16:52Z DEBUG pact_matching]      generators: Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '/users' to '/users' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] expected content type = '*/*', actual content type = '*/*'
[2021-02-10T07:16:52Z DEBUG pact_matching] content type header matcher = 'None'
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '2' to '3' using Type
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing 'Basic YWRtaW46YWRtaW4=' to 'Basic YWRtaW46YWRtaW4=' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] --> Mismatches: []
[2021-02-10T07:16:52Z INFO  pact_matching] comparing to expected Request ( method: GET, path: /users, query: Some({"id": ["3"]}), headers: Some({"Accept": ["application/hal+json"], "Authorization": ["Basic YWRtaW46YWRtaW4="]}), body: Missing )
[2021-02-10T07:16:52Z DEBUG pact_matching]      body: ''
[2021-02-10T07:16:52Z DEBUG pact_matching]      matching_rules: MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T07:16:52Z DEBUG pact_matching]      generators: Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '/users' to '/users' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] expected content type = '*/*', actual content type = '*/*'
[2021-02-10T07:16:52Z DEBUG pact_matching] content type header matcher = 'None'
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing '3' to '3' using Type
[2021-02-10T07:16:52Z DEBUG pact_matching::matchers] String -> String: comparing 'Basic YWRtaW46YWRtaW4=' to 'Basic YWRtaW46YWRtaW4=' using Equality
[2021-02-10T07:16:52Z DEBUG pact_matching] --> Mismatches: []
[2021-02-10T07:16:52Z DEBUG pact_mock_server::hyper_server] Test context = {"mockServer": Object({"href": String("http://127.0.0.1:1234"), "port": Number(1234)})}
[2021-02-10T07:16:52Z INFO  pact_mock_server::hyper_server] Request matched, sending response Response ( status: 200, headers: Some({"content-type": ["application/hal+json"]}), body: Present(50 bytes, applic
@saw-jan saw-jan added the bug Indicates an unexpected problem or unintended behavior label Feb 10, 2021
@saw-jan
Copy link
Author

saw-jan commented Feb 10, 2021

@mefellows

for (let user of users) {
      aGETUserInfoByIdQueryInteraction(
        provider,
        user.id,
        user.username,
        user.email
      );
    }

this is expected to create 3 interactions

@mefellows
Copy link
Member

Yes, I wrote the message and as I hit send I saw my mistake and deleted it - but I didn't sneak it past you it seems! :)

The strange thing is, the log looks good to me.

This does seem like a bug, but a quick workaround would be to enclose the whole thing in a loop (rather than have the executeTest function run all 3).

@saw-jan
Copy link
Author

saw-jan commented Feb 10, 2021

it('using in a loop: "fromProviderState" as query', async () => {
    for (let user of users) {
      aGETUserInfoByIdQueryInteraction(
        provider,
        user.id,
        user.username,
        user.email
      );
      await provider.executeTest(async () => {        
       await client.getUserByIdQuery(user.id);
      });
   }
  });

Tried this one too but no luck

Log is different though

Error: Mock server failed with the following mismatches: 

      1) The following request was expected but not received: 
          Method: GET
          Path: /users
          Query String: id=2
          Headers:
            Accept: application/hal+json
            Authorization: Basic YWRtaW46YWRtaW4=

LOG

[2021-02-10T10:04:14Z DEBUG pact_js_v3] Initialising Pact native library version 0.0.6
[2021-02-10T10:04:14Z DEBUG pact_js_v3] Request = Request ( method: GET, path: /users, query: Some({"id": ["1"]}), headers: Some({"Authorization": ["Basic YWRtaW46YWRtaW4="], "Accept": ["application/hal+json"]}), body: Missing )
[2021-02-10T10:04:14Z DEBUG pact_js_v3] Request matching rules = MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T10:04:14Z DEBUG pact_js_v3] Request generators = Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T10:04:14Z DEBUG pact_js_v3] Response = Response ( status: 200, headers: Some({"content-type": ["application/hal+json"]}), body: Present(50 bytes, application/json) )
[2021-02-10T10:04:14Z DEBUG pact_js_v3] Response matching rules = MatchingRules { rules: {"body": MatchingRuleCategory { name: "body", rules: {"$.id": RuleList { rules: [Number], rule_logic: And }, "$.username": RuleList { rules: [Type], rule_logic: And }, "$.email": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T10:04:14.157Z] DEBUG: pact@10.0.0-beta.30/95931 on JT101: Initialised native library 0.0.6

 RUNS  tests/pactV3.test.js
[2021-02-10T10:04:14Z DEBUG pact_mock_server::hyper_server] Creating pact request from hyper request
[2021-02-10T10:04:14Z INFO  pact_mock_server::hyper_server] Received request Request ( method: GET, path: /users, query: Some({"id": ["1"]}), headers: Some({"authorization": ["Basic YWRtaW46YWRtaW4="], "user-agent": ["axios/0.21.1"], "host": ["127.0.0.1:1234"], "connection": ["close"], "accept": ["application/hal+json"]}), body: Empty )
[2021-02-10T10:04:14Z INFO  pact_matching] comparing to expected Request ( method: GET, path: /users, query: Some({"id": ["1"]}), headers: Some({"Authorization": ["Basic YWRtaW46YWRtaW4="], "Accept": ["application/hal+json"]}), body: Missing )
[2021-02-10T10:04:14Z DEBUG pact_matching]      body: ''
[2021-02-10T10:04:14Z DEBUG pact_matching]      matching_rules: MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T10:04:14Z DEBUG pact_matching]      generators: Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T10:04:14Z DEBUG pact_matching::matchers] String -> String: comparing '/users' to '/users' using Equality
[2021-02-10T10:04:14Z DEBUG pact_matching] expected content type = '*/*', actual content type = '*/*'
[2021-02-10T10:04:14Z DEBUG pact_matching] content type header matcher = 'None'
[2021-02-10T10:04:14Z DEBUG pact_matching::matchers] String -> String: comparing '1' to '1' using Type
[2021-02-10T10:04:14Z DEBUG pact_matching::matchers] String -> String: comparing 'Basic YWRtaW46YWRtaW4=' to 'Basic YWRtaW46YWRtaW4=' using Equality
[2021-02-10T10:04:14Z DEBUG pact_matching] --> Mismatches: []
[2021-02-10T10:04:14Z DEBUG pact_mock_server::hyper_server] Test context = {"mockServer": Object({"href": String("http://127.0.0.1:1234"), "port": Number(1234)})}
[2021-02-10T10:04:14Z INFO  pact_mock_server::hyper_server] Request matched, sending response Response ( status: 200, headers: Some({"content-type": ["application/hal+json"]}), body: Present(50 bytes, application/json) )
[2021-02-10T10:04:14Z DEBUG pact_mock_server::hyper_server]      body: '{"email":"adam@mail.com","id":1,"username":"Adam"}'
[2021-02-10T10:04:14Z INFO  pact_mock_server::mock_server] Writing pact out to '/mnt/sda1/www/pactv3/tests/pacts/client-server.json'
[2021-02-10T10:04:14Z DEBUG pact_matching::models] Merging pact with file "/mnt/sda1/www/pactv3/tests/pacts/client-server.json"
[2021-02-10T10:04:14Z DEBUG pact_js_v3] Request = Request ( method: GET, path: /users, query: Some({"id": ["2"]}), headers: Some({"Accept": ["application/hal+json"], "Authorization": ["Basic YWRtaW46YWRtaW4="]}), body: Missing )
[2021-02-10T10:04:14Z DEBUG pact_js_v3] Request matching rules = MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T10:04:14Z DEBUG pact_js_v3] Request generators = Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T10:04:14Z DEBUG pact_js_v3] Response = Response ( status: 200, headers: Some({"content-type": ["application/hal+json"]}), body: Present(48 bytes, application/json) )
[2021-02-10T10:04:14Z DEBUG pact_js_v3] Response matching rules = MatchingRules { rules: {"body": MatchingRuleCategory { name: "body", rules: {"$.email": RuleList { rules: [Type], rule_logic: And }, "$.username": RuleList { rules: [Type], rule_logic: And }, "$.id": RuleList { rules: [Number], rule_logic: And }} }} }
[2021-02-10T10:04:14Z DEBUG pact_js_v3] Response generators = Generators { categories: {} }
[2021-02-10T10:04:14Z DEBUG pact_mock_server::mock_server] Started mock server on 0.0.0.0:1234
[2021-02-10T10:04:14Z DEBUG pact_mock_server::hyper_server] Creating pact request from hyper request
[2021-02-10T10:04:14Z INFO  pact_mock_server::hyper_server] Received request Request ( method: GET, path: /users, query: Some({"id": ["2"]}), headers: Some({"user-agent": ["axios/0.21.1"], "authorization": ["Basic YWRtaW46YWRtaW4="], "accept": ["application/hal+json"], "host": ["127.0.0.1:1234"], "connection": ["close"]}), body: Empty )
[2021-02-10T10:04:14Z INFO  pact_matching] comparing to expected Request ( method: GET, path: /users, query: Some({"id": ["1"]}), headers: Some({"Authorization": ["Basic YWRtaW46YWRtaW4="], "Accept": ["application/hal+json"]}), body: Missing )
[2021-02-10T10:04:14Z DEBUG pact_matching]      body: ''
[2021-02-10T10:04:14Z DEBUG pact_matching]      matching_rules: MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T10:04:14Z DEBUG pact_matching]      generators: Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T10:04:14Z DEBUG pact_matching::matchers] String -> String: comparing '/users' to '/users' using Equality
[2021-02-10T10:04:14Z DEBUG pact_matching] expected content type = '*/*', actual content type = '*/*'
[2021-02-10T10:04:14Z DEBUG pact_matching] content type header matcher = 'None'
[2021-02-10T10:04:14Z DEBUG pact_matching::matchers] String -> String: comparing '1' to '2' using Type
[2021-02-10T10:04:14Z DEBUG pact_matching::matchers] String -> String: comparing 'Basic YWRtaW46YWRtaW4=' to 'Basic YWRtaW46YWRtaW4=' using Equality
[2021-02-10T10:04:14Z DEBUG pact_matching] --> Mismatches: []
[2021-02-10T10:04:14Z INFO  pact_matching] comparing to expected Request ( method: GET, path: /users, query: Some({"id": ["2"]}), headers: Some({"Accept": ["application/hal+json"], "Authorization": ["Basic YWRtaW46YWRtaW4="]}), body: Missing )
[2021-02-10T10:04:14Z DEBUG pact_matching]      body: ''
[2021-02-10T10:04:14Z DEBUG pact_matching]      matching_rules: MatchingRules { rules: {"query": MatchingRuleCategory { name: "query", rules: {"id": RuleList { rules: [Type], rule_logic: And }} }} }
[2021-02-10T10:04:14Z DEBUG pact_matching]      generators: Generators { categories: {QUERY: {"id": ProviderStateGenerator("${id}", None)}} }
[2021-02-10T10:04:14Z DEBUG pact_matching::matchers] String -> String: comparing '/users' to '/users' using Equality
[2021-02-10T10:04:14Z DEBUG pact_matching] expected content type = '*/*', actual content type = '*/*'
[2021-02-10T10:04:14Z DEBUG pact_matching] content type header matcher = 'None'
[2021-02-10T10:04:14Z DEBUG pact_matching::matchers] String -> String: comparing '2' to '2' using Type
[2021-02-10T10:04:14Z DEBUG pact_matching::matchers] String -> String: comparing 'Basic YWRtaW46YWRtaW4=' to 'Basic YWRtaW46YWRtaW4=' using Equality
[2021-02-10T10:04:14Z DEBUG pact_matching] --> Mismatches: []
[2021-02-10T10:04:14Z DEBUG pact_mock_server::hyper_server] Test context = {"mockServer": Object({"href": String("http://127.0.0.1:1234"), "port": Number(1234)})}
[2021-02-10T10:04:14Z INFO  pact_mock_server::hyper_server] Request matched, sending response Response ( status: 200, headers: Some({"content-type": ["application/hal+json"]}), body: Present(50 bytes

@individual-it
Copy link
Contributor

I reproduced the issue with the provider-state-injected example see https://gist.github.com/47213e2386aefeeb3cea31663b9c90c1
it seems to me that for the mock-server its not a new interaction if the query uses fromProviderState

both response are send and answered, but the answer is always the one coming from the first interaction

GET /accounts/search/findOneByAccountNumberId?accountNumber=100 HTTP/1.1
Accept: application/hal+json
Referer: http://localhost/
User-Agent: Mozilla/5.0 (linux) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/16.4.0
Accept-Language: en
Origin: http://localhost
host: 127.0.0.1:1234
accept-encoding: gzip, deflate
Connection: keep-alive

HTTP/1.1 200 OK
access-control-allow-origin: *
access-control-allow-headers: *
access-control-allow-methods: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH
access-control-expose-headers: Location, Link
content-type: application/hal+json
content-length: 301
date: Mon, 22 Feb 2021 05:19:42 GMT

{"_links":{"account":{"href":"http://localhost:8080/accounts/100"},"self":{"href":"http://localhost:8080/accounts/100"}},"accountNumber":{"id":100},"accountRef":"Test001","createdDate":"2021-02-22T11:04:42.490+05:45","id":1,"lastModifiedDate":"2021-02-22T11:04:42.490+05:45","name":"Test","version":8}GET /accounts/search/findOneByAccountNumberId?accountNumber=200 HTTP/1.1
Accept: application/hal+json
Referer: http://localhost/
User-Agent: Mozilla/5.0 (linux) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/16.4.0
Accept-Language: en
Origin: http://localhost
host: 127.0.0.1:1234
accept-encoding: gzip, deflate
Connection: keep-alive

HTTP/1.1 200 OK
access-control-allow-origin: *
access-control-allow-headers: *
access-control-allow-methods: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH
access-control-expose-headers: Location, Link
content-type: application/hal+json
content-length: 301
date: Mon, 22 Feb 2021 05:19:42 GMT

{"_links":{"account":{"href":"http://localhost:8080/accounts/100"},"self":{"href":"http://localhost:8080/accounts/100"}},"accountNumber":{"id":100},"accountRef":"Test001","createdDate":"2021-02-22T11:04:42.504+05:45","id":1,"lastModifiedDate":"2021-02-22T11:04:42.504+05:45","name":"Test","version":7}

using a query without fromProviderState makes the mock server to distinguish between the interactions and give the correct response.

I guess the issue is rather in the mock server than in the js lib

@mefellows
Copy link
Member

Looks to be an upstream issue. @uglyog mind casting your eyes over this one?

@rholshausen
Copy link

Looks like only one interaction is being setup, i.e., it is seeing the 3 with different example values as the same interaction.

@mefellows mefellows added the upstream Indicates that an issue relates to an upstream problem (such as in pact-reference) label Aug 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior upstream Indicates that an issue relates to an upstream problem (such as in pact-reference)
Projects
Status: New Issue
Development

No branches or pull requests

4 participants