From 28885c1459ad561608c63266c90f90378550e224 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 14 Apr 2017 12:30:57 +0200 Subject: [PATCH] JSONPath compilation fails when there is an array, attribute that is an array and then attribute on an execute() without this change we're not referrencing arrays properly in json path. For some reason (that I don't remember) we had a deferrencing via 'get' in the code. 'get' is not present in JSON Path. That's why it was failing with this change we're deferrencing arrays via `.` or index fixes #251 --- .../builder/JUnitMethodBodyBuilder.groovy | 5 +- .../builder/MethodBodyBuilderSpec.groovy | 109 ++++++++++++++++++ 2 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMethodBodyBuilder.groovy index 8d0919bafe..eaf1f3be42 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMethodBodyBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMethodBodyBuilder.groovy @@ -107,10 +107,7 @@ abstract class JUnitMethodBodyBuilder extends RequestProcessingMethodBodyBuilder } private String getMapKeyReferenceString(String property, Map.Entry entry) { - if (entry.value instanceof ExecutionProperty) { - return provideProperJsonPathNotation(property) + "." + entry.key - } - return property + """.get(\\\"$entry.key\\\")""" + return provideProperJsonPathNotation(property) + "." + entry.key } private String provideProperJsonPathNotation(String property) { diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy new file mode 100644 index 0000000000..f19160ccbf --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy @@ -0,0 +1,109 @@ +/* + * Copyright 2013-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder + +import org.junit.Rule +import org.springframework.boot.test.rule.OutputCapture +import org.springframework.cloud.contract.spec.Contract +import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties +import org.springframework.cloud.contract.verifier.dsl.WireMockStubVerifier +import org.springframework.cloud.contract.verifier.util.SyntaxChecker +import spock.lang.Issue +import spock.lang.Shared +import spock.lang.Specification + +class MethodBodyBuilderSpec extends Specification implements WireMockStubVerifier { + + @Rule OutputCapture capture = new OutputCapture() + + @Shared ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties( + assertJsonSize: true + ) + + @Issue('#251') + def "should work with execute and arrays [#methodBuilderName]"() { + given: + Contract contractDsl = Contract.make { + request { + method 'GET' + urlPath '/foo' + headers { + accept(applicationJson()) + contentType(applicationJson()) + } + } + response { + status 200 + body ([ + myArray:[ + [ + notABugGeneratedHere: $(c("foo"), p(execute('assertThat((String)$it).isEqualTo("foo")'))), + anotherArrayNeededForBug:[ + [ + optionalNotEmpty: $(c("foo"), p(execute('assertThat((String)$it).isEqualTo("12")'))) + ] + ], + yetAnotherArrayNeededForBug:[ + [ + optionalNotEmpty: $(c("foo"), p(execute('assertThat((String)$it).isEqualTo("22")'))) + ] + ] + ], + [ + anotherArrayNeededForBug2:[ + [ + optionalNotEmpty: $(c("foo"), p(execute('assertThat((String)$it).isEqualTo("122")'))) + ] + ] + ], + ] + ]) + headers { + contentType(applicationJson()) + } + } + } + MethodBodyBuilder builder = methodBuilder(contractDsl) + BlockBuilder blockBuilder = new BlockBuilder(" ") + when: + builder.appendTo(blockBuilder) + def test = blockBuilder.toString() + then: + test.contains('$.myArray[0].anotherArrayNeededForBug[0].optionalNotEmpty') + !test.contains('cursor') + !test.contains('REGEXP>>') + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + and: + String jsonSample = '''\ +String json = "{\\"myArray\\":[{\\"notABugGeneratedHere\\":\\"foo\\",\\"anotherArrayNeededForBug\\":[{\\"optionalNotEmpty\\":\\"12\\"}],\\"yetAnotherArrayNeededForBug\\":[{\\"optionalNotEmpty\\":\\"22\\"}]},{\\"anotherArrayNeededForBug2\\":[{\\"optionalNotEmpty\\":\\"122\\"}]}]}"; +DocumentContext parsedJson = JsonPath.parse(json); +''' + and: + LinkedList lines = [] as LinkedList + test.eachLine { if (it.contains("assertThatJson") || it.contains("assertThat((String")) lines << it else it } + lines.addFirst(jsonSample) + SyntaxChecker.tryToRun(methodBuilderName, lines.join("\n")) + where: + methodBuilderName | methodBuilder + "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) } + } + +}