Fixed the way we clone bodies in response
without this change we are not doing a deep copy of a collection thus we're accidentaly removing the original value with this change we ensure that a deep copy is made fixes #229
This commit is contained in:
@@ -24,7 +24,7 @@ import groovy.transform.CompileStatic
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@CompileStatic
|
||||
class ExecutionProperty {
|
||||
class ExecutionProperty implements Serializable {
|
||||
|
||||
private static final String PLACEHOLDER_VALUE = '$it'
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import groovy.transform.CompileStatic
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@CompileStatic
|
||||
class OptionalProperty {
|
||||
class OptionalProperty implements Serializable {
|
||||
final Object value
|
||||
|
||||
OptionalProperty(Object value) {
|
||||
|
||||
@@ -22,12 +22,22 @@ import groovy.json.JsonOutput
|
||||
import groovy.transform.PackageScope
|
||||
import groovy.transform.TypeChecked
|
||||
import org.apache.commons.lang3.StringEscapeUtils
|
||||
import org.springframework.cloud.contract.spec.internal.*
|
||||
import org.springframework.cloud.contract.spec.internal.BodyMatcher
|
||||
import org.springframework.cloud.contract.spec.internal.BodyMatchers
|
||||
import org.springframework.cloud.contract.spec.internal.DslProperty
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
|
||||
import org.springframework.cloud.contract.spec.internal.Header
|
||||
import org.springframework.cloud.contract.spec.internal.MatchingStrategy
|
||||
import org.springframework.cloud.contract.spec.internal.MatchingType
|
||||
import org.springframework.cloud.contract.spec.internal.NamedProperty
|
||||
import org.springframework.cloud.contract.spec.internal.OptionalProperty
|
||||
import org.springframework.cloud.contract.spec.internal.QueryParameter
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.util.ContentType
|
||||
import org.springframework.cloud.contract.verifier.util.JsonPaths
|
||||
import org.springframework.cloud.contract.verifier.util.JsonToJsonPathsConverter
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter
|
||||
import org.springframework.util.SerializationUtils
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@@ -386,7 +396,12 @@ abstract class MethodBodyBuilder {
|
||||
bb.endBlock().endBlock()
|
||||
}
|
||||
|
||||
// Doing a clone doesn't work for nested lists...
|
||||
private Object cloneBody(Object object) {
|
||||
if (object instanceof List) {
|
||||
byte[] serializedObject = SerializationUtils.serialize(object)
|
||||
return SerializationUtils.deserialize(serializedObject)
|
||||
}
|
||||
try {
|
||||
return object.clone()
|
||||
} catch (CloneNotSupportedException e) {
|
||||
@@ -405,7 +420,7 @@ abstract class MethodBodyBuilder {
|
||||
try {
|
||||
return JsonPath.parse(body).read(path)
|
||||
} catch (PathNotFoundException e) {
|
||||
throw new IllegalStateException("Entry for the provided JSON path [${path}] doesn't exist in the body [${JsonOutput.toJson(body)}]", e)
|
||||
throw new IllegalStateException("Entry for the provided JSON path <${path}> doesn't exist in the body <${JsonOutput.toJson(body)}>", e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import groovy.json.JsonSlurper
|
||||
import groovy.util.logging.Slf4j
|
||||
import org.springframework.cloud.contract.spec.internal.*
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.util.SerializationUtils
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@@ -86,7 +87,12 @@ class JsonToJsonPathsConverter {
|
||||
return jsonCopy
|
||||
}
|
||||
|
||||
// Doing a clone doesn't work for nested lists...
|
||||
private static Object cloneBody(Object object) {
|
||||
if (object instanceof List) {
|
||||
byte[] serializedObject = SerializationUtils.serialize(object)
|
||||
return SerializationUtils.deserialize(serializedObject)
|
||||
}
|
||||
try {
|
||||
return object.clone()
|
||||
} catch (CloneNotSupportedException e) {
|
||||
|
||||
@@ -353,7 +353,46 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements
|
||||
builder.appendTo(blockBuilder)
|
||||
then:
|
||||
IllegalStateException e = thrown(IllegalStateException)
|
||||
e.message.contains("Entry for the provided JSON path [\$.nonExistingPhoneNumbers[*].number] doesn't exist in the body")
|
||||
e.message.contains("Entry for the provided JSON path <\$.nonExistingPhoneNumbers[*].number> doesn't exist in the body")
|
||||
where:
|
||||
methodBuilderName | methodBuilder | rootElement
|
||||
"MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | '\\$'
|
||||
"MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } | '$'
|
||||
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | '\\$'
|
||||
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) } | '$'
|
||||
}
|
||||
|
||||
@Issue("#229")
|
||||
def "should work for matchers and body with json array[#methodBuilderName]"() {
|
||||
given:
|
||||
Contract contractDsl = Contract.make {
|
||||
request {
|
||||
method 'GET'
|
||||
url '/api/v1/xxxx'
|
||||
body(12000)
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
body ([[
|
||||
[ access_token: '123']
|
||||
]])
|
||||
headers {
|
||||
contentType(applicationJson())
|
||||
}
|
||||
testMatchers {
|
||||
jsonPath('''$[0][0].access_token''', byEquality())
|
||||
}
|
||||
}
|
||||
}
|
||||
MethodBodyBuilder builder = methodBuilder(contractDsl)
|
||||
BlockBuilder blockBuilder = new BlockBuilder(" ")
|
||||
and:
|
||||
builder.appendTo(blockBuilder)
|
||||
String test = blockBuilder.toString()
|
||||
when:
|
||||
SyntaxChecker.tryToCompile(methodBuilderName, test)
|
||||
then:
|
||||
test.contains('assertThat(parsedJson.read("' + rootElement + '[0][0].access_token", String.class)).isEqualTo("123")')
|
||||
where:
|
||||
methodBuilderName | methodBuilder | rootElement
|
||||
"MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | '\\$'
|
||||
|
||||
Reference in New Issue
Block a user