From 99d393b8e3fa4c3146a0d61789570f8aa4e3cad3 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Tue, 14 Feb 2017 14:03:04 +0100 Subject: [PATCH] Fixed the way we work with body that is just a number fixes #226 --- .../cloud/contract/spec/internal/Body.groovy | 4 ++ .../verifier/builder/MethodBodyBuilder.groovy | 10 ++++- .../verifier/util/ContentUtils.groovy | 38 ++++++++++--------- .../util/JsonToJsonPathsConverter.groovy | 10 ++++- .../MockMvcMethodBodyBuilderSpec.groovy | 32 ++++++++++++++++ 5 files changed, 75 insertions(+), 19 deletions(-) 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 b13935c6dd..8ea190531f 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 @@ -48,6 +48,10 @@ class Body extends DslProperty { this("${bodyAsValue}") } + Body(Number bodyAsValue) { + super(bodyAsValue) + } + Body(GString bodyAsValue) { super(bodyAsValue, bodyAsValue) } 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 520d93d876..90d305084c 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 @@ -297,7 +297,7 @@ abstract class MethodBodyBuilder { private void addJsonResponseBodyCheck(BlockBuilder bb, convertedResponseBody, BodyMatchers bodyMatchers) { appendJsonPath(bb, getResponseAsString()) - Object copiedBody = convertedResponseBody.clone() + Object copiedBody = cloneBody(convertedResponseBody) convertedResponseBody = JsonToJsonPathsConverter.removeMatchingJsonPaths(convertedResponseBody, bodyMatchers) JsonPaths jsonPaths = new JsonToJsonPathsConverter(configProperties).transformToJsonPathWithTestsSideValues(convertedResponseBody) jsonPaths.each { @@ -386,6 +386,14 @@ abstract class MethodBodyBuilder { bb.endBlock().endBlock() } + private Object cloneBody(Object object) { + try { + return object.clone() + } catch (CloneNotSupportedException e) { + return object + } + } + protected Object value(def body, BodyMatcher bodyMatcher) { if (bodyMatcher.matchingType() == MatchingType.EQUALITY || !bodyMatcher.value()) { return retrieveObjectByPath(body, bodyMatcher.path()) 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 1ea245519a..c58220c430 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 @@ -66,7 +66,7 @@ class ContentUtils { * @param valueProvider - provider of values either for server or client side * @return JSON structure with replaced client / server side parts */ - public static Object extractValue(GString bodyAsValue, ContentType contentType, Closure valueProvider) { + static Object extractValue(GString bodyAsValue, ContentType contentType, Closure valueProvider) { if (bodyAsValue.isEmpty()){ return bodyAsValue } @@ -95,7 +95,7 @@ class ContentUtils { } } - public static ContentType getClientContentType(GString bodyAsValue) { + static ContentType getClientContentType(GString bodyAsValue) { try { extractValueForJSON(bodyAsValue, GET_STUB_SIDE) return ContentType.JSON @@ -110,7 +110,7 @@ class ContentUtils { } } - public static ContentType getClientContentType(String bodyAsValue) { + static ContentType getClientContentType(String bodyAsValue) { try { new JsonSlurper().parseText(bodyAsValue) return ContentType.JSON @@ -124,11 +124,11 @@ class ContentUtils { } } - public static ContentType getClientContentType(Object bodyAsValue) { + static ContentType getClientContentType(Object bodyAsValue) { return ContentType.UNKNOWN } - public static ContentType getClientContentType(Map bodyAsValue) { + static ContentType getClientContentType(Map bodyAsValue) { try { JsonOutput.toJson(bodyAsValue) return ContentType.JSON @@ -137,7 +137,7 @@ class ContentUtils { } } - public static ContentType getClientContentType(List bodyAsValue) { + static ContentType getClientContentType(List bodyAsValue) { try { JsonOutput.toJson(bodyAsValue) return ContentType.JSON @@ -153,7 +153,7 @@ class ContentUtils { ) } - public static Object extractValue(GString bodyAsValue, Closure valueProvider) { + static Object extractValue(GString bodyAsValue, Closure valueProvider) { return extractValue(bodyAsValue, ContentType.UNKNOWN, valueProvider) } @@ -275,7 +275,7 @@ class ContentUtils { return val[1] } - public static ContentType recognizeContentTypeFromHeader(Headers headers) { + static ContentType recognizeContentTypeFromHeader(Headers headers) { String content = headers?.entries.find { it.name == "Content-Type" } ?.clientValue?.toString() if (content?.endsWith("json")) { return ContentType.JSON @@ -289,7 +289,7 @@ class ContentUtils { return ContentType.UNKNOWN } - public static MatchingStrategy.Type getEqualsTypeFromContentType(ContentType contentType) { + static MatchingStrategy.Type getEqualsTypeFromContentType(ContentType contentType) { switch (contentType) { case ContentType.JSON: return MatchingStrategy.Type.EQUAL_TO_JSON @@ -299,7 +299,7 @@ class ContentUtils { return MatchingStrategy.Type.EQUAL_TO } - public static ContentType recognizeContentTypeFromContent(GString gstring) { + static ContentType recognizeContentTypeFromContent(GString gstring) { if (isJsonType(gstring)) { return ContentType.JSON } @@ -309,15 +309,15 @@ class ContentUtils { return ContentType.UNKNOWN } - public static ContentType recognizeContentTypeFromContent(Map jsonMap) { + static ContentType recognizeContentTypeFromContent(Map jsonMap) { return ContentType.JSON } - public static ContentType recognizeContentTypeFromContent(List jsonList) { + static ContentType recognizeContentTypeFromContent(List jsonList) { return ContentType.JSON } - public static ContentType recognizeContentTypeFromContent(String string) { + static ContentType recognizeContentTypeFromContent(String string) { try { new JsonSlurper().parseText(string) return ContentType.JSON @@ -326,11 +326,15 @@ class ContentUtils { } } - public static ContentType recognizeContentTypeFromContent(Object gstring) { + static ContentType recognizeContentTypeFromContent(Number number) { + return ContentType.TEXT + } + + static ContentType recognizeContentTypeFromContent(Object gstring) { return ContentType.UNKNOWN } - public static boolean isJsonType(GString gstring) { + static boolean isJsonType(GString gstring) { if (gstring.isEmpty()) { return false } @@ -349,7 +353,7 @@ class ContentUtils { return false } - public static boolean isXmlType(GString gstring) { + static boolean isXmlType(GString gstring) { GString stringWithoutValues = new GStringImpl( gstring.values.collect({ it instanceof String || it instanceof GString ? it.toString() : escapeXml11(it.toString()) @@ -365,7 +369,7 @@ class ContentUtils { return false } - public static ContentType recognizeContentTypeFromMatchingStrategy(MatchingStrategy.Type type) { + static ContentType recognizeContentTypeFromMatchingStrategy(MatchingStrategy.Type type) { switch (type) { case MatchingStrategy.Type.EQUAL_TO_XML: return ContentType.XML diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverter.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverter.groovy index 1e4ae5a137..26cae3741f 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverter.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverter.groovy @@ -70,7 +70,7 @@ class JsonToJsonPathsConverter { * @return json with removed entries */ static def removeMatchingJsonPaths(def json, BodyMatchers bodyMatchers) { - def jsonCopy = json.clone() + def jsonCopy = cloneBody(json) DocumentContext context = JsonPath.parse(jsonCopy) if (bodyMatchers?.hasMatchers()) { bodyMatchers.jsonPathMatchers().each { BodyMatcher matcher -> @@ -86,6 +86,14 @@ class JsonToJsonPathsConverter { return jsonCopy } + private static Object cloneBody(Object object) { + try { + return object.clone() + } catch (CloneNotSupportedException e) { + return object + } + } + /** * For the given matcher converts it into a JSON path * that checks the regex pattern or equality 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 74e80123e3..6b7503e697 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 @@ -2158,4 +2158,36 @@ World.'''""" "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } "JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) } } + + @Issue("#226") + def "should work properly when body is an integer [#methodBuilderName]"() { + given: + Contract contractDsl = Contract.make { + request { + method 'GET' + url '/api/v1/xxxx' + body(12000) + } + response { + status 200 + body(12000) + } + } + MethodBodyBuilder builder = methodBuilder(contractDsl) + BlockBuilder blockBuilder = new BlockBuilder(" ") + and: + builder.appendTo(blockBuilder) + String test = blockBuilder.toString() + when: + SyntaxChecker.tryToCompile(methodBuilderName, test) + then: + requestAssertion(test) + responseAssertion(test) + where: + methodBuilderName | methodBuilder | requestAssertion | responseAssertion + "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | { String body -> body.contains("body('''12000''')") } | { String body -> body.contains('responseBody == "12000"') } + "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } | { String body -> body.contains('body("12000")') } | { String body -> body.contains('assertThat(responseBody).isEqualTo("12000");') } + "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | { String body -> body.contains(""".method('GET', entity('12000', 'text/plain'))""") } | { String body -> body.contains('responseBody == "12000"') } + "JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) } | { String body -> body.contains(""".method("GET", entity("12000", "text/plain"))""") } | { String body -> body.contains('assertThat(responseBody).isEqualTo("12000")') } + } }