Reputation: 81
I'm looking to perform custom assertions on fields in JSON loaded from file.
I understand that we have fuzzy matching, but I'd like to perform something more custom e.g. have a function which parses a date as a LocalDateTime:
public class DateUtil {
public static boolean matchesMyDateFormat(String dateStr) {
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
LocalDateTime.parse(dateStr, formatter);
} catch (DateTimeParseException e) {
return false;
}
return true;
}
}
This would be called by the following:
* def matchesMyDateFormat =
"""
function fn(dateX){
return Java.type('com.karate.DateUtil').matchesMyDateFormat(dateX);
}
"""
* def expected = read('expected.json')
* def actual = read('actual.json')
* match expected == actual
Where expected.json looks like this:
{
"date1" : "#? matchesMyDateFormat(_)"
}
NB this is specifically for JSON loaded from file and not on JSON which is specified in the feature file itself (e.g. like for isValidTime() here: https://github.com/intuit/karate/blob/master/karate-junit4/src/test/java/com/intuit/karate/junit4/demos/schema-like.feature).
Few reasons for wishing to do it this way:
NB: I've read through the docs and the other SO answers related to date assertions and believe this is a slightly different ask.
Is the above possible to do in Karate at the moment?
Upvotes: 3
Views: 1219
Reputation: 81
What I was trying was in fact a valid use-case (as is the alternative solution kindly suggested by Peter Thomas in his answer).
The reason my particular variation wasn't working was this error:
07:22:50.421 assertion failed: path: $.date1, actual: '#? matchesMyDateFormat(_)', expected: '2020-06-10T14:44:57.060Z', reason: not equal
I noticed with a fresh pair of eyes that I should flip the match statement from:
* match expected == actual
To:
* match actual == expected
This way is required in order for Karate to work its magic and call the custom function in expected.json.
Upvotes: 2
Reputation: 58058
You can add functions in karate-config.js
which will be "global". For example:
var config = {};
config.isValidDate = read('classpath:is-valid-date.js');
return config;
Now you can use isValidDate(_)
in any feature. Note that JS functions can take multiple arguments, e.g:
* match foo == { bar: "#? isValidDate(_, 'MYFORMAT')" }
In 0.9.6.RC4 we made improvements so that you can move complex conditional logic and even match
operations into re-usable JS files: https://github.com/intuit/karate/issues/1202
Be warned, doing a lot of this may lead to un-readable tests: https://stackoverflow.com/a/54126724/143475
One hint, you can use karate.forEach()
to extract all date-fields into an array and then a single match each
may work.
Finally, if you still feel there is "too much code in your feature files", I don't know, maybe you need to consult a magician.
Upvotes: 2