Merge branch '2.2.x'
This commit is contained in:
@@ -320,13 +320,15 @@ class JsonToJsonPathsConverter {
|
||||
}
|
||||
|
||||
JsonPaths transformToJsonPathWithTestsSideValues(def json,
|
||||
Closure parsingClosure = MapConverter.JSON_PARSING_CLOSURE) {
|
||||
return transformToJsonPathWithValues(json, SERVER_SIDE, parsingClosure)
|
||||
Closure parsingClosure = MapConverter.JSON_PARSING_CLOSURE,
|
||||
boolean includeEmptyCheck = false) {
|
||||
return transformToJsonPathWithValues(json, SERVER_SIDE, parsingClosure, includeEmptyCheck)
|
||||
}
|
||||
|
||||
JsonPaths transformToJsonPathWithStubsSideValues(def json,
|
||||
Closure parsingClosure = MapConverter.JSON_PARSING_CLOSURE) {
|
||||
return transformToJsonPathWithValues(json, CLIENT_SIDE, parsingClosure)
|
||||
Closure parsingClosure = MapConverter.JSON_PARSING_CLOSURE,
|
||||
boolean includeEmptyCheck = false) {
|
||||
return transformToJsonPathWithValues(json, CLIENT_SIDE, parsingClosure, includeEmptyCheck)
|
||||
}
|
||||
|
||||
static JsonPaths transformToJsonPathWithStubsSideValuesAndNoArraySizeCheck(def json,
|
||||
@@ -336,11 +338,11 @@ class JsonToJsonPathsConverter {
|
||||
}
|
||||
|
||||
private JsonPaths transformToJsonPathWithValues(def json, boolean clientSide,
|
||||
Closure parsingClosure = MapConverter.JSON_PARSING_CLOSURE) {
|
||||
if (!json) {
|
||||
Closure parsingClosure = MapConverter.JSON_PARSING_CLOSURE,
|
||||
boolean includeEmptyCheck = false) {
|
||||
if (json == null || (!json && !includeEmptyCheck)) {
|
||||
return new JsonPaths()
|
||||
}
|
||||
JsonPaths pathsAndValues = [] as Set
|
||||
Object convertedJson = MapConverter.
|
||||
getClientOrServerSideValues(json, clientSide, parsingClosure)
|
||||
Object jsonWithPatterns = ContentUtils.
|
||||
@@ -349,6 +351,11 @@ class JsonToJsonPathsConverter {
|
||||
new DelegatingJsonVerifiable(JsonAssertion.
|
||||
assertThat(JsonOutput.toJson(jsonWithPatterns))
|
||||
.withoutThrowingException())
|
||||
JsonPaths pathsAndValues = [] as Set
|
||||
if (isRootElement(methodBufferingJsonPathVerifiable) && !json) {
|
||||
pathsAndValues.add(methodBufferingJsonPathVerifiable.isEmpty())
|
||||
return pathsAndValues
|
||||
}
|
||||
traverseRecursivelyForKey(jsonWithPatterns, methodBufferingJsonPathVerifiable,
|
||||
{ MethodBufferingJsonVerifiable key, Object value ->
|
||||
if (value instanceof ExecutionProperty || !(key instanceof FinishedDelegatingJsonVerifiable)) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.cloud.contract.verifier.builder;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
@@ -98,13 +99,19 @@ class JsonBodyVerificationBuilder implements BodyMethodGeneration, ClassVerifier
|
||||
}
|
||||
Object copiedBody = cloneBody(convertedResponseBody);
|
||||
convertedResponseBody = JsonToJsonPathsConverter.removeMatchingJsonPaths(convertedResponseBody, bodyMatchers);
|
||||
|
||||
// If it was a map or list where all elements covered by matchers - json paths
|
||||
// should not include empty check
|
||||
boolean includeEmptyCheck = !mapOrListBodyReducedToEmpty(copiedBody, convertedResponseBody);
|
||||
|
||||
// remove quotes from fromRequest objects before picking json paths
|
||||
TestSideRequestTemplateModel templateModel = hasRequestBody()
|
||||
? TestSideRequestTemplateModel.from(contract.getRequest()) : null;
|
||||
convertedResponseBody = MapConverter.transformValues(convertedResponseBody,
|
||||
returnReferencedEntries(templateModel), parsingClosure);
|
||||
JsonPaths jsonPaths = new JsonToJsonPathsConverter(assertJsonSize)
|
||||
.transformToJsonPathWithTestsSideValues(convertedResponseBody, parsingClosure);
|
||||
.transformToJsonPathWithTestsSideValues(convertedResponseBody, parsingClosure, includeEmptyCheck);
|
||||
|
||||
DocumentContext finalParsedRequestBody = parsedRequestBody;
|
||||
jsonPaths.forEach(it -> {
|
||||
String method = it.method();
|
||||
@@ -118,6 +125,17 @@ class JsonBodyVerificationBuilder implements BodyMethodGeneration, ClassVerifier
|
||||
return convertedResponseBody;
|
||||
}
|
||||
|
||||
private boolean mapOrListBodyReducedToEmpty(Object originalBody, Object convertedBody) {
|
||||
int origSize = originalBody instanceof Map ? ((Map) originalBody).size() : -1;
|
||||
int convertedSize = convertedBody instanceof Map ? ((Map) convertedBody).size() : -1;
|
||||
if (origSize > 0 && convertedSize == 0) {
|
||||
return true;
|
||||
}
|
||||
origSize = originalBody instanceof List ? ((List) originalBody).size() : -1;
|
||||
convertedSize = convertedBody instanceof List ? ((List) convertedBody).size() : -1;
|
||||
return (origSize > 0 && convertedSize == 0);
|
||||
}
|
||||
|
||||
private boolean hasRequestBody() {
|
||||
return contract.getRequest() != null && contract.getRequest().getBody() != null;
|
||||
}
|
||||
|
||||
@@ -579,6 +579,66 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock
|
||||
"webclient" | { configProperties.testMode = TestMode.WEBTESTCLIENT }
|
||||
}
|
||||
|
||||
@Issue('#1423')
|
||||
def 'should generate assertions for a response body containing an empty list with #methodBuilderName'() {
|
||||
given:
|
||||
Contract contractDsl = Contract.make {
|
||||
request {
|
||||
method "GET"
|
||||
url "/url"
|
||||
}
|
||||
response {
|
||||
status OK()
|
||||
body("[]")
|
||||
}
|
||||
}
|
||||
methodBuilder()
|
||||
when:
|
||||
String test = singleTestGenerator(contractDsl)
|
||||
then:
|
||||
test.contains("""assertThatJson(parsedJson).isEmpty()""")
|
||||
and:
|
||||
stubMappingIsValidWireMockStub(contractDsl)
|
||||
and:
|
||||
SyntaxChecker.tryToCompile(methodBuilderName, test)
|
||||
where:
|
||||
methodBuilderName | methodBuilder
|
||||
"spock" | { properties.testFramework = TestFramework.SPOCK }
|
||||
"testng" | { properties.testFramework = TestFramework.TESTNG }
|
||||
"mockmvc" | { properties.testMode = TestMode.MOCKMVC }
|
||||
"webclient" | { properties.testMode = TestMode.WEBTESTCLIENT }
|
||||
}
|
||||
|
||||
@Issue('#1423')
|
||||
def 'should generate assertions for a response body containing an empty map with #methodBuilderName'() {
|
||||
given:
|
||||
Contract contractDsl = Contract.make {
|
||||
request {
|
||||
method "GET"
|
||||
url "/url"
|
||||
}
|
||||
response {
|
||||
status OK()
|
||||
body("{}")
|
||||
}
|
||||
}
|
||||
methodBuilder()
|
||||
when:
|
||||
String test = singleTestGenerator(contractDsl)
|
||||
then:
|
||||
test.contains("""assertThatJson(parsedJson).isEmpty()""")
|
||||
and:
|
||||
stubMappingIsValidWireMockStub(contractDsl)
|
||||
and:
|
||||
SyntaxChecker.tryToCompile(methodBuilderName, test)
|
||||
where:
|
||||
methodBuilderName | methodBuilder
|
||||
"spock" | { properties.testFramework = TestFramework.SPOCK }
|
||||
"testng" | { properties.testFramework = TestFramework.TESTNG }
|
||||
"mockmvc" | { properties.testMode = TestMode.MOCKMVC }
|
||||
"webclient" | { properties.testMode = TestMode.WEBTESTCLIENT }
|
||||
}
|
||||
|
||||
def 'should generate regex assertions for map objects in response body with #methodBuilderName'() {
|
||||
given:
|
||||
Contract contractDsl = Contract.make {
|
||||
|
||||
@@ -446,6 +446,68 @@ response:
|
||||
"custom" | { properties.testMode = TestMode.CUSTOM }
|
||||
}
|
||||
|
||||
@Issue('#1423')
|
||||
def 'should generate assertions for a response body containing an empty list with #methodBuilderName'() {
|
||||
given:
|
||||
String contract = """\
|
||||
---
|
||||
description: Returns an empty collection
|
||||
request:
|
||||
method: GET
|
||||
urlPath: /url
|
||||
response:
|
||||
status: 200
|
||||
body: []
|
||||
"""
|
||||
Contract contractDsl = fromYaml(contract)
|
||||
methodBuilder()
|
||||
when:
|
||||
String test = singleTestGenerator(contractDsl)
|
||||
then:
|
||||
test.contains("""assertThatJson(parsedJson).isEmpty()""")
|
||||
and:
|
||||
stubMappingIsValidWireMockStub(contractDsl)
|
||||
and:
|
||||
SyntaxChecker.tryToCompile(methodBuilderName, test)
|
||||
where:
|
||||
methodBuilderName | methodBuilder
|
||||
"spock" | { properties.testFramework = TestFramework.SPOCK }
|
||||
"testng" | { properties.testFramework = TestFramework.TESTNG }
|
||||
"mockmvc" | { properties.testMode = TestMode.MOCKMVC }
|
||||
"webclient" | { properties.testMode = TestMode.WEBTESTCLIENT }
|
||||
}
|
||||
|
||||
@Issue('#1423')
|
||||
def 'should generate assertions for a response body containing an empty map with #methodBuilderName'() {
|
||||
given:
|
||||
String contract = """\
|
||||
---
|
||||
description: Returns an empty map
|
||||
request:
|
||||
method: GET
|
||||
urlPath: /url
|
||||
response:
|
||||
status: 200
|
||||
body: {}
|
||||
"""
|
||||
Contract contractDsl = fromYaml(contract)
|
||||
methodBuilder()
|
||||
when:
|
||||
String test = singleTestGenerator(contractDsl)
|
||||
then:
|
||||
test.contains("""assertThatJson(parsedJson).isEmpty()""")
|
||||
and:
|
||||
stubMappingIsValidWireMockStub(contractDsl)
|
||||
and:
|
||||
SyntaxChecker.tryToCompile(methodBuilderName, test)
|
||||
where:
|
||||
methodBuilderName | methodBuilder
|
||||
"spock" | { properties.testFramework = TestFramework.SPOCK }
|
||||
"testng" | { properties.testFramework = TestFramework.TESTNG }
|
||||
"mockmvc" | { properties.testMode = TestMode.MOCKMVC }
|
||||
"webclient" | { properties.testMode = TestMode.WEBTESTCLIENT }
|
||||
}
|
||||
|
||||
def 'should generate regex assertions for map objects in response body with #methodBuilderName'() {
|
||||
given:
|
||||
String contract = '''\
|
||||
|
||||
Reference in New Issue
Block a user