[V3] Mock server fails with mismatches when using fromProviderState in iterated interaction
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: [email protected]/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":"[email protected]","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":"[email protected]","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
@mefellows
for (let user of users) {
aGETUserInfoByIdQueryInteraction(
provider,
user.id,
user.username,
user.email
);
}
this is expected to create 3 interactions
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).
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: [email protected]/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":"[email protected]","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
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
Looks to be an upstream issue. @uglyog mind casting your eyes over this one?
Looks like only one interaction is being setup, i.e., it is seeing the 3 with different example values as the same interaction.