Responses are typically primed using the following interface in Traffic Parrot. There are similar interfaces for other protocols.
We refer to this request and response pair as a mapping. Traffic Parrot uses the request information in the mapping to determine whether an incoming request matches this mapping or not. If it does, then the response information in the mapping is sent as a response to the incoming request.
The typical way of working with a small number of mappings is to use exact request body matchers such as equalTo, equalToJson or equalToXml and specify a particular response body that should be the response for a particular request body.
For example, we could have exact equalToXml mappings for the following three XML request and response messages:
<stockRequest> <checkId>1</checkId> <item>apple</item> </stockRequest>
<stockResponse> <checkId>1</checkId> <date>2017-12-14T14:15:21Z</date> <item>apple</item> <available>4</available> </stockResponse>
<stockRequest> <checkId>2</checkId> <item>apple</item> </stockRequest>
<stockResponse> <checkId>2</checkId> <date>2017-12-14T14:28:56Z</date> <item>apple</item> <available>0</available> </stockResponse>
<stockRequest> <checkId>3</checkId> <item>pear</item> </stockRequest>
<stockResponse> <checkId>3</checkId> <date>2017-12-14T14:20:25Z</date> <item>pear</item> <available>5</available> </stockResponse>
This can work well for a small number of mappings where we know what the request and response should look like ahead of time.
Dynamic responses are a way to avoid the limitations discussed above. We could simulate similar behaviour to the three interactions above using the following dynamic response:
<stockResponse> <checkId>{{xPath request.body '/stockRequest/checkId/text()'}}</checkId> <date>{{now format="yyyy-MM-dd'T'HH:mm:ssZ"}}</date> <item>{{xPath request.body '/stockRequest/item/text()'}}</item> <available>{{#ifEven (xPath request.body '/stockRequest/checkId/text()')}}0{{else}}5{{/ifEven}}</available> </stockResponse>
We can use this as the response in a mapping with a simple matchesXPath matcher for the request that matches all the requests:
/stockRequest
Here is what some interactions look like as they are replayed:
<stockRequest> <checkId>1</checkId> <item>apple</item> </stockRequest>
<stockResponse> <checkId>1</checkId> <date>2018-01-08T14:15:21Z</date> <item>apple</item> <available>4</available> </stockResponse>
<stockRequest> <checkId>2</checkId> <item>apple</item> </stockRequest>
<stockResponse> <checkId>2</checkId> <date>2018-01-08T14:16:21Z</date> <item>apple</item> <available>0</available> </stockResponse>
<stockRequest> <checkId>3</checkId> <item>pear</item> </stockRequest>
<stockResponse> <checkId>3</checkId> <date>2018-01-08T14:17:21Z</date> <item>pear</item> <available>5</available> </stockResponse>
<stockRequest> <checkId>4</checkId> <item>orange</item> </stockRequest>
<stockResponse> <checkId>4</checkId> <date>2018-01-08T14:18:21Z</date> <item>orange</item> <available>0</available> </stockResponse>
<request id="123"/>
<response id="123"/>
<response id="{{xPath request.body '/request/@id'}}"/>
<request> <id>100</id> <name>example</name> </request>
<response> <id>100</id> <name>example</name> </response>
<response> <id>{{xPath request.body '/request/id/text()'}}</id> <name>{{xPath request.body '/request/name/text()'}}</name> </response>
{ "type": "request", "id": 100, "name": "example" }
{ "type": "response", "id": 100, "name": "example" }
{ "type": "response", "id": {{jsonPath request.body '$.id'}}, "name": "{{jsonPath request.body '$.name'}}" }
<request> <item id="1"/> <item id="2"/> <item id="3"/> </request>
<response> <item id="1" status="OK"/> <item id="2" status="OK"/> <item id="3" status="OK"/> </response>
<response> {{#each (xPathList request.body '/request') }} <item id="{{ xPath this '/item/@id' }}" status="OK"/> {{/each}} </response>
{ "type": "request", "items": [ { "id": 1 }, { "id": 2 }, { "id": 3 } ] }
{ "type": "response", "items": [ { "id": 1, "status": "OK" }, { "id": 2, "status": "OK" }, { "id": 3, "status": "OK" } ] }
{ "type": "response", "items": [ {{#each (jsonPathList request.body '$.items') }} { "id": {{ jsonPath this '$.id' }}, "status": "OK" }{{#unless @last}},{{/unless}} {{/each}} ] }
<date>{{now format="yyyy-MM-dd'T'HH:mm:ssZ"}}</date>
<date>{{now format="dd/MM/yyyy"}}</date>
{{regex request.fileName '(.*).REQ' }}.RSP
Let us say you wanted to add a different tag to the IBM MQ response message body based on a request XML tag value. So for example when a request with a value starting with 90* is received, you will return one type of XML response tag, and otherwise, you will return a different XML tag in the response.
Request 1:<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <GetFoo> <FooId> <BarId>102322323832</BarId> </FooId> </GetFoo> </soap:Body> </soap:Envelope>Expected response 1:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <RESPONSE_TYPE_10xxxxxxxxx/> </soap:Body> </soap:Envelope>Request 2:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <GetFoo> <FooId> <BarId>90374747436363</BarId> </FooId> </GetFoo> </soap:Body> </soap:Envelope>Expected response 2:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <RESPONSE_TYPE_20xxxxxxxxx/> </soap:Body> </soap:Envelope>We can do this by using this response body template:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> {{#equal (regex (xPath request.body '//GetFoo/FooId/BarId/text()') '(.{2})\d+') '90'}} <RESPONSE_TYPE_20xxxxxxxxx/> {{else}} <RESPONSE_TYPE_10xxxxxxxxx/> {{/equal}} </soap:Body> </soap:Envelope>Here is how it works: