spring-cloud-contract: bodyMatchers - minOccurrences failing with SimpleObjects List.
We are trying to implement contracts for list of objects which contains a list of basic objects (Integer) we just saw that having something like
body([
[
listNumbers: [
50, 100, 150, 200, 300, 1000
],
]
])
bodyMatchers {
jsonPath('$[*].listNumbers[*]', byRegex(positiveInt()))
jsonPath('$[*].listNumbers', byType {
minOccurrence(0)
})
}
is generating
assertThat((java.lang.Iterable) parsedJson.read("$[*].listNumbers[*]", java.util.Collection.class)).as("$[*].listNumbers[*]").allElementsMatch("([1-9]\\d*)");
assertThat((Object) parsedJson.read("$[*].listNumbers")).isInstanceOf(java.util.List.class);
assertThat((java.lang.Iterable) parsedJson.read("$[*].listNumbers", java.util.Collection.class)).as("$[*].listNumbers").hasFlattenedSizeGreaterThanOrEqualTo(0);
which fail for whatever minOcurrence greater than 0 since counter in the implementation is never update if we have an simple list of objects…
private int flattenedSize(int counter, Object object) {
if (object instanceof Map) {
return counter + ((Map) object).size();
}
else if (object instanceof Iterator) {
Iterator iterator = ((Iterator) object);
while (iterator.hasNext()) {
Object next = iterator.next();
counter = flattenedSize(counter, next);
}
return counter;
}
else if (object instanceof Collection) {
return flattenedSize(counter, ((Collection) object).iterator());
}
return counter;
}
May be I miss a call to the size(Iterable iterable) function.
But if we just have
body(
[
listNumbers: [
50, 100, 150, 200, 300, 1000
],
]
)
bodyMatchers {
jsonPath('$.listNumbers[*]', byRegex(positiveInt()))
jsonPath('$.listNumbers', byType {
minOccurrence(0)
})
}
we got
assertThat((java.lang.Iterable) parsedJson.read("$.listNumbers[*]", java.util.Collection.class)).as("$.listNumbers[*]").allElementsMatch("([1-9]\\d*)");
assertThat((Object) parsedJson.read("$.listNumbers")).isInstanceOf(java.util.List.class);
assertThat((java.lang.Iterable) parsedJson.read("$.listNumbers", java.util.Collection.class)).as("$.listNumbers").hasSizeGreaterThanOrEqualTo(0);
which works more better with values greater than 1, in fact it works.
So we are a bit lost about if the actual behaviour is the expected one or there is a bug but it’s like a bit frustrating trying to understand why this behaviour.
Nowadays we found this is happening with Spring Cloud Versions 2.0.4.RELEASE and 2.1.1.RELEASE, so looks like is the expected way to be? is this is true, how we can achieve to get a contract as we want, have the same validation expresion for a return object and a list of objects of the same type. Kind Regards.
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 28 (5 by maintainers)
Commits related to this issue
- Fix flattened size counter. Fixes gh-1108. Signed-off-by: Olga Maciaszek-Sharma <olga.maciaszek@gmail.com> — committed to spring-cloud/spring-cloud-contract by OlgaMaciaszek 5 years ago
- Fix flattened size counter. Fixes gh-1108. (#1229) Signed-off-by: Olga Maciaszek-Sharma <olga.maciaszek@gmail.com> — committed to spring-cloud/spring-cloud-contract by OlgaMaciaszek 5 years ago
Ok I’ll need a sample to replicate this. Could you create a small one please?
Great, that will be extremely helpful, thank you.