From 98b7b49459f51f260b711f3d1e335cc8cf9e1a11 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Tue, 24 Oct 2017 11:47:28 +0200 Subject: [PATCH] Fixes the way tests from simple json are generated json can have a very primitive structure. Without this change we have bugs when we try to generate tests fixes #443 --- .../builder/JUnitMethodBodyBuilder.groovy | 4 +- .../verifier/builder/MethodBodyBuilder.groovy | 13 +++++-- .../RestAssuredJUnitMethodBodyBuilder.groovy | 2 +- .../verifier/util/ContentUtils.groovy | 12 +++--- .../MockMvcMethodBodyBuilderSpec.groovy | 37 ++++++++++++++++++- 5 files changed, 55 insertions(+), 13 deletions(-) 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 e341c4249d..0079442d2d 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 @@ -177,8 +177,8 @@ abstract class JUnitMethodBodyBuilder extends RequestProcessingMethodBodyBuilder return buildEscapedMatchesMethod(headerValue) + ";" } - private String buildEscapedMatchesMethod(Pattern headerValue) { - String escapedHeader = convertUnicodeEscapesIfRequired("$headerValue") + private String buildEscapedMatchesMethod(Pattern escapedValue) { + String escapedHeader = convertUnicodeEscapesIfRequired("$escapedValue") return createMatchesMethod(escapedHeader) } 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 38b9d6dd0b..af7fbd0279 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 @@ -334,12 +334,16 @@ abstract class MethodBodyBuilder { addColonIfRequired(bb) // TODO xml validation } else { - bb.addLine(getSimpleResponseBodyString(getResponseAsString())) - processText(bb, "", convertedResponseBody) - addColonIfRequired(bb) + simpleTextResponseBodyCheck(bb, convertedResponseBody) } } + private void simpleTextResponseBodyCheck(BlockBuilder bb, convertedResponseBody) { + bb.addLine(getSimpleResponseBodyString(getResponseAsString())) + processText(bb, "", convertedResponseBody) + addColonIfRequired(bb) + } + private void addJsonResponseBodyCheck(BlockBuilder bb, convertedResponseBody, BodyMatchers bodyMatchers) { appendJsonPath(bb, getResponseAsString()) Object copiedBody = cloneBody(convertedResponseBody) @@ -373,6 +377,9 @@ abstract class MethodBodyBuilder { } } } + if (!(convertedResponseBody instanceof Map || convertedResponseBody instanceof List)) { + simpleTextResponseBodyCheck(bb, convertedResponseBody) + } processBodyElement(bb, "", "", convertedResponseBody) } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredJUnitMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredJUnitMethodBodyBuilder.groovy index c37fe36681..f8efde8959 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredJUnitMethodBodyBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredJUnitMethodBodyBuilder.groovy @@ -62,7 +62,7 @@ class RestAssuredJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder { @Override protected String getResponseBodyPropertyComparisonString(String property, Pattern value) { - return null + return """assertThat(responseBody).${createHeaderComparison(value)}""" } @Override diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy index ea0aa40b39..f28195056c 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy @@ -16,12 +16,16 @@ package org.springframework.cloud.contract.verifier.util +import java.util.regex.Matcher +import java.util.regex.Pattern + import groovy.json.JsonException import groovy.json.JsonOutput import groovy.json.JsonSlurper import groovy.transform.TypeChecked import groovy.util.logging.Slf4j import org.codehaus.groovy.runtime.GStringImpl + import org.springframework.cloud.contract.spec.internal.DslProperty import org.springframework.cloud.contract.spec.internal.ExecutionProperty import org.springframework.cloud.contract.spec.internal.Headers @@ -29,13 +33,9 @@ import org.springframework.cloud.contract.spec.internal.MatchingStrategy import org.springframework.cloud.contract.spec.internal.NamedProperty import org.springframework.cloud.contract.spec.internal.OptionalProperty -import java.util.regex.Matcher -import java.util.regex.Pattern - import static org.apache.commons.lang3.StringEscapeUtils.escapeJava import static org.apache.commons.lang3.StringEscapeUtils.escapeJson import static org.apache.commons.lang3.StringEscapeUtils.escapeXml11 - /** * A utility class that can operate on a message body basing on the provided Content Type. * @@ -283,10 +283,10 @@ class ContentUtils { static ContentType recognizeContentTypeFromHeader(Headers headers) { String content = headers?.entries.find { it.name == "Content-Type" } ?.clientValue?.toString() - if (content?.endsWith("json")) { + if (content?.contains("json")) { return ContentType.JSON } - if (content?.endsWith("xml")) { + if (content?.contains("xml")) { return ContentType.XML } if (content?.contains("text")) { 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 f61cc01cba..6c0f94584d 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 @@ -2096,7 +2096,7 @@ DocumentContext parsedJson = JsonPath.parse(json); } @Issue('#172') - def "should resolve plain text properly via headers"() { + def "should resolve plain text properly via headers"() { given: Contract contractDsl = Contract.make { request { @@ -2128,6 +2128,41 @@ DocumentContext parsedJson = JsonPath.parse(json); "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}''' } + @Issue('#443') + def "should resolve plain text that happens to be a valid json for [#methodBuilderName]"() { + given: + Contract contractDsl = Contract.make { + request { + method 'GET' + url '/foo' + } + response { + status 200 + headers { + contentType(applicationJsonUtf8()) + } + body( + value(client('true'), server(regex("true|false"))) + ) + } + } + MethodBodyBuilder builder = methodBuilder(contractDsl) + BlockBuilder blockBuilder = new BlockBuilder(" ") + when: + builder.appendTo(blockBuilder) + def test = blockBuilder.toString() + then: + testAssertion(test) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + where: + methodBuilderName | methodBuilder | testAssertion + "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | { String testContents -> testContents.contains("""responseBody ==~ java.util.regex.Pattern.compile('true|false')""") } + "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } | { String testContents -> testContents.contains("""assertThat(responseBody).matches("true|false");""") } + "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | { String testContents -> testContents.contains("""responseBody ==~ java.util.regex.Pattern.compile('true|false')""") } + "JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) } | { String testContents -> testContents.contains("""assertThat(responseBody).matches("true|false");""") } + } + @Issue('#169') def "should escape quotes properly using [#methodBuilderName]"() { given: