diff --git a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/Body.groovy b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/Body.groovy index 100210ca99..407a37500f 100644 --- a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/Body.groovy +++ b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/Body.groovy @@ -53,6 +53,10 @@ class Body extends DslProperty { super(bodyAsValue) } + Body(String bodyAsValue) { + super(bodyAsValue, bodyAsValue) + } + Body(GString bodyAsValue) { super(bodyAsValue, bodyAsValue) } diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/build.gradle b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/build.gradle index 2d843a0ecc..7790251c72 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/build.gradle +++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/build.gradle @@ -23,7 +23,7 @@ ext { ] } -project.version = findProperty('verifierVersion') ?: '2.1.0.BUILD-SNAPSHOT' +project.version = findProperty('verifierVersion') apply plugin: 'groovy' apply from: "$rootDir/gradle/release.gradle" apply plugin: 'eclipse' @@ -32,8 +32,8 @@ apply plugin: 'checkstyle' group = 'org.springframework.cloud' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 repositories { mavenLocal() @@ -75,7 +75,7 @@ dependencies { } testCompile 'info.solidsoft.spock:spock-global-unroll:0.5.0' testCompile gradleTestKit() - checkstyle 'org.springframework.cloud:spring-cloud-build:1.0.2.RELEASE' + checkstyle 'org.springframework.cloud:spring-cloud-build:2.0.3.RELEASE' } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilder.groovy index 3539b23cb3..aa02e58844 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilder.groovy @@ -367,6 +367,14 @@ abstract class MethodBodyBuilder { private void addJsonResponseBodyCheck(BlockBuilder bb, convertedResponseBody, BodyMatchers bodyMatchers) { appendJsonPath(bb, getResponseAsString()) + DocumentContext parsedRequestBody + if (contract.request?.body) { + def testSideRequestBody = MapConverter.getTestSideValues(contract.request.body) + parsedRequestBody = JsonPath.parse(testSideRequestBody) + if (convertedResponseBody instanceof String && !textContainsJsonPathTemplate(convertedResponseBody)) { + convertedResponseBody = templateProcessor.transform(contract.request, convertedResponseBody.toString()) + } + } Object copiedBody = cloneBody(convertedResponseBody) convertedResponseBody = JsonToJsonPathsConverter.removeMatchingJsonPaths(convertedResponseBody, bodyMatchers) // remove quotes from fromRequest objects before picking json paths @@ -374,11 +382,6 @@ abstract class MethodBodyBuilder { TestSideRequestTemplateModel.from(contract.request) : null convertedResponseBody = MapConverter.transformValues(convertedResponseBody, returnReferencedEntries(templateModel)) JsonPaths jsonPaths = new JsonToJsonPathsConverter(configProperties).transformToJsonPathWithTestsSideValues(convertedResponseBody) - DocumentContext parsedRequestBody - if (contract.request?.body) { - def requestBody = MapConverter.getTestSideValues(contract.request.body) - parsedRequestBody = JsonPath.parse(requestBody) - } jsonPaths.each { String method = it.method() method = processIfTemplateIsPresent(method, parsedRequestBody) @@ -448,8 +451,7 @@ abstract class MethodBodyBuilder { } protected String processIfTemplateIsPresent(String method, DocumentContext parsedRequestBody) { - if (templateProcessor.containsTemplateEntry(method) && - templateProcessor.containsJsonPathTemplateEntry(method) && contract.request?.body) { + if (textContainsJsonPathTemplate(method) && contract.request?.body) { // Unquoting the values of non strings String jsonPathEntry = templateProcessor.jsonPathFromTemplateEntry(method) Object object = parsedRequestBody.read(jsonPathEntry) @@ -464,6 +466,11 @@ abstract class MethodBodyBuilder { return method } + protected boolean textContainsJsonPathTemplate(String method) { + return templateProcessor.containsTemplateEntry(method) && + templateProcessor.containsJsonPathTemplateEntry(method) + } + protected void methodForEqualityCheck(BodyMatcher bodyMatcher, BlockBuilder bb, Object copiedBody) { String path = quotedAndEscaped(bodyMatcher.path()) Object retrievedValue = value(copiedBody, bodyMatcher) diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/MapConverter.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/MapConverter.groovy index e5565a8f81..1bea23558a 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/MapConverter.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/MapConverter.groovy @@ -69,6 +69,8 @@ class MapConverter { def json = new JsonSlurper().parseText(value) if (json instanceof Map) { return convert(json, closure) + } else if (json instanceof List) { + return transformValues(json, closure) } } catch (Exception ignore) { } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy index c9348237c8..2b3d8d4f39 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy @@ -447,7 +447,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } } - def "should generate assertions for array inside response body element with #methodBuilderName"() { + def "should generate assertions for array inside response body element with #methodBuilderName"() { given: Contract contractDsl = Contract.make { request { @@ -2647,6 +2647,60 @@ DocumentContext parsedJson = JsonPath.parse(json); "JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) } | { String body -> body.contains('assertThat(response.getHeaderString("Authorization")).isEqualTo("foo secret bar");') } } + @Issue("#230") + def "should manage to reference request in response via WireMock native entries [#methodBuilderName]"() { + given: + //tag::template_contract[] + Contract contractDsl = Contract.make { + request { + method 'GET' + url('/api/v1/xxxx') { + queryParameters { + parameter("foo", "bar") + parameter("foo", "bar2") + } + } + headers { + header(authorization(), "secret") + header(authorization(), "secret2") + } + body(foo: "bar", baz: 5) + } + response { + status OK() + headers { + contentType(applicationJson()) + } + body(''' + { + "responseFoo": "{{{ jsonPath request.body '$.foo' }}}", + "responseBaz": {{{ jsonPath request.body '$.baz' }}}, + "responseBaz2": "Bla bla {{{ jsonPath request.body '$.foo' }}} bla bla" + } + '''.toString()) + } + } + //end::template_contract[] + MethodBodyBuilder builder = methodBuilder(contractDsl) + BlockBuilder blockBuilder = new BlockBuilder(" ") + and: + builder.appendTo(blockBuilder) + String test = blockBuilder.toString() + when: + SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) + then: + !test.contains('''DslProperty''') + test.contains('''assertThatJson(parsedJson).field("['responseFoo']").isEqualTo("bar")''') + test.contains('''assertThatJson(parsedJson).field("['responseBaz']").isEqualTo(5)''') + test.contains('''assertThatJson(parsedJson).field("['responseBaz2']").isEqualTo("Bla bla bar bla bla")''') + 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) } + } + def "should generate JUnit assertions with cookies"() { given: MethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDslWithCookiesValue, properties)