I am using karate 1.1.0 version. I need to create a mock service where an object is optional. When I create a service like this
Feature: Karate netty - testing for optional. The request payload may have either benefiaciary.cardInfo object or beneficiary.cardTokenInfo object
Ex: "beneficiary":{
"cardInfo":{
"number": "12345"
}
}
OR
"beneficiary":{
"cardTokenInfo":{
"token": "98765"
}
}
Background:
* def happyPathResponse_json = {status: 'Payment accepted'}
* def invalidResponse_json = {status: 'Invalid request'}
## Happy path if cardNumber is passed
Scenario: pathMatches('/mock/payment/v5')
&& request.beneficiary.cardInfo.number == '12345'
* def response = happyPathResponse_json
* def responseStatus = 201
* def responseHeaders = {'Content-Type': 'application/json'}
## Happy path if card token is passed
Scenario: pathMatches('/mock/payment/v5')
&& request.beneficiary.cardTokenInfo.number == '98765'
* def response = happyPathResponse_json
* def responseStatsus = 201
* def responseHeaders = {'Content-Type':'application/json'}
## Catch all scenario if nothing matches
Scenario: pathMatches('/mock/payment/v5')
* def response = invalidRespose_json
* def responseStatus = 201
* def responseHeaders = {'Content-Type': 'application/json'}
The code works when I pass the request payload as below
{
"beneficiary:{
"cardInfo":{
"number": "12345"
}
}
}
However when I pass the payload as below
{
"beneficiary": {
"cardTokenInfo":{
"token": "98765"
}
}
}
The karate netty server throws error as
Cannot read property "number" from undefined
This is expected, because it is not able to go beyond the first scenario, where it expects that "cardInfo" object will be passed. To solve this issue I am trying to use schema match to check that
when beneficiary.cardInfo == '#present' then scenario should match.
The schema match works BUT not in case of netty/mock server. This is what I tried
Scenario: pathMatches('/mock/payment/v5')
&& request.beneficiary.cardInfo == '#present'
&& request.beneficiary.cardInfo.number == '12345'
* def response = happyPathResponse_json
* def responseStatus = 201
* def responseHeaders = {'Content-Type': 'application/json'}
The schema match is coming as false with karate netty/mock but it is actually true when I test it with karate test.
What am I missing here? Does schema match not work with karate netty? If not then what is the alternative. I don't want to use
"* if() karate.abort()" as it will abort the feature and hence next set of scenarios will not be executed.
UPDATE: I found a work around using "bodyPath". In one of questions answered by @PeterThomas , he mentioned that in with "pathMatches", the condition code is treated as javascript and provided a workaround for XML but it worked for json as well.
When I replace
request.beneficiary.cardInfo.number == '12345'
With
bodyPath('$.beneficiary.cardInfo.number') == '12345'
I get the scenario working as well but again '#present' is still not working.
SOLUTION: For people who landed on this page looking for a similar solution.Here are two ways:
Option 1: Use bodyPath
bodyPath('$.beneficiary.cardInfo.number') == '12345'
Option 2: As @PeterThomas already confirmed that only JS is supported(see comment below). we can use karate.match to first confirm that a key is present.
pathMatches('/mock/payment/v5') && karate.match("request.beneficiary.cardInfo == '#present'").pass && request.beneficiary.cardInfo.number == '12345'
NOTE You will also find a third solution where you can just use
request.beneficiary.cardInfo.number.contains('12345')
This solution will work BUT if you try and pass a request payload with an unknown field then your code will blow up ex:
"beneficiary":{
"cardInfo":{
"someUnknownKey": "12345"
}
}