I have started to implement PACT for CDC testing. How can I handle the scenario where we pass different parameters in the path for different environments?
For example my test calls a function which requests some data from a service by hitting the endpoint and passing some parameters. Very standard.
E.G: api/nodeId/${nodeId}/userId/${userId}
For different environments (QA, UAT etc) unique data specific to that environment must be passed in order to elicit a valid 200 response. So in my example carId and userId will need to be different for each env. When I set my test up originally I used our QA environment and got the following contract generated.
{
"consumer": {
"name": "myConsumer"
},
"provider": {
"name": "myProvider"
},
"interactions": [
{
"description": "a request to view nodes",
"request": {
"method": "GET",
"path": "/api/nodeId/RRTT6-3AFA-4B5B-BF76-5B6AC7/userId/123456789",
"headers": {
"Content-Type": "application/x-www-form-urlencoded",
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"startTime": 1549652248000,
"endTime": 1549911448000,
"startPrice": 83576,
"reservePrice": 83876,
"price": 84576,
"status": null,
"groupList": [
"78945"
],
"bids": 0,
}
}
}
],
"metadata": {
"pactSpecification": {
"version": "2.0.0"
}
}
}
As you can see the path in the contract has a nodeId and userId hardcoded. If I tried to validate against a different environment these tests would fail. So how can I re-use the same contract for different environments? Currently for different environments I am generating a separate contract for each, but seems like there must be another way.
You can use the term
Matcher for dynamic paths, but as Fabrico warns, having specific pieces of data per environment is a dangerous game to be playing. It is common for the provider to have different IDs for all kinds of reasons, so where possible try to decouple your tests from being dependent on these.
e.g. with path matchers:
const { Pact, Matchers } = require('@pact-foundation/pact');
const { term } = Matchers;
provider.addInteraction({
state: 'has node ID 1234 and user with ID 5678',
uponReceiving: 'a request to view nodes',
withRequest: {
method: 'GET',
api/nodeId/${nodeId}/userId/${userId}
path: term({ generate: '/api/nodeId/RRTT6-3AFA-4B5B-BF76-5B6AC7/userId/123456789', matcher: '/api/nodeId/[A-Z0-9\-]+/userId/[0-9]+' })
},
willRespondWith: {
status: 200,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: { ... }
}
})