diff --git a/specs/spring-cloud-contract-spec-java/src/main/java/org/springframework/cloud/contract/spec/internal/FromFileProperty.java b/specs/spring-cloud-contract-spec-java/src/main/java/org/springframework/cloud/contract/spec/internal/FromFileProperty.java index 40fd297815..eb357bbe4b 100644 --- a/specs/spring-cloud-contract-spec-java/src/main/java/org/springframework/cloud/contract/spec/internal/FromFileProperty.java +++ b/specs/spring-cloud-contract-spec-java/src/main/java/org/springframework/cloud/contract/spec/internal/FromFileProperty.java @@ -54,6 +54,14 @@ public class FromFileProperty implements Serializable { return byte[].class.equals(this.type) || Byte[].class.equals(this.type); } + public boolean isJson() { + return this.fileName().endsWith(".json"); + } + + public boolean isXml() { + return this.fileName().endsWith(".xml"); + } + public String asString() { try { return new String(asBytes(), this.charset); 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 91a527cb5d..3e84955348 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 @@ -47,6 +47,7 @@ import static org.apache.commons.text.StringEscapeUtils.unescapeXml import static org.springframework.cloud.contract.verifier.util.ContentType.DEFINED import static org.springframework.cloud.contract.verifier.util.ContentType.JSON import static org.springframework.cloud.contract.verifier.util.ContentType.UNKNOWN +import static org.springframework.cloud.contract.verifier.util.ContentType.XML /** * A utility class that can operate on a message body basing on the provided Content Type. @@ -116,7 +117,7 @@ class ContentUtils { if (JSON == contentType) { return extractValueForJSON(bodyAsValue, valueProvider) } - if (contentType == ContentType.XML) { + if (contentType == XML) { return extractValueForXML(bodyAsValue, valueProvider) } // else Brute force :( @@ -151,7 +152,7 @@ class ContentUtils { getXmlSlurperWithDefaultErrorHandler() .parseText( extractValueForXML(bodyAsValue, GET_STUB_SIDE).toString()) - return ContentType.XML + return XML } catch (Exception ignored) { extractValueForGString(bodyAsValue, GET_STUB_SIDE) @@ -169,7 +170,7 @@ class ContentUtils { try { getXmlSlurperWithDefaultErrorHandler() .parseText(bodyAsValue) - return ContentType.XML + return XML } catch (Exception ignored) { return UNKNOWN @@ -415,7 +416,7 @@ class ContentUtils { return JSON } if (content?.contains("xml")) { - return ContentType.XML + return XML } if (content?.contains("text")) { return ContentType.TEXT @@ -446,7 +447,7 @@ class ContentUtils { switch (contentType) { case JSON: return MatchingStrategy.Type.EQUAL_TO_JSON - case ContentType.XML: + case XML: return MatchingStrategy.Type.EQUAL_TO_XML } return MatchingStrategy.Type.EQUAL_TO @@ -457,7 +458,7 @@ class ContentUtils { return JSON } if (isXmlType(gstring)) { - return ContentType.XML + return XML } return UNKNOWN } @@ -481,7 +482,7 @@ class ContentUtils { } catch (Exception ignored) { if (isXmlType("$string")) { - return ContentType.XML + return XML } return UNKNOWN } @@ -492,6 +493,15 @@ class ContentUtils { } static ContentType recognizeContentTypeFromContent(Object object) { + if (object instanceof FromFileProperty) { + FromFileProperty property = (FromFileProperty) object; + if (property.isJson()) { + return JSON + } else if (property.isXml()) { + return XML + } + object = object.isByte() ? object.asBytes() : object.asString() + } if (object instanceof GString) { return recognizeContentTypeFromContent((GString) object) } @@ -556,7 +566,7 @@ class ContentUtils { static ContentType recognizeContentTypeFromMatchingStrategy(MatchingStrategy.Type type) { switch (type) { case MatchingStrategy.Type.EQUAL_TO_XML: - return ContentType.XML + return XML case MatchingStrategy.Type.EQUAL_TO_JSON: return JSON } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderWithMatchersSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderWithMatchersSpec.groovy index 07eb8557ea..d04d447ab9 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderWithMatchersSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderWithMatchersSpec.groovy @@ -744,4 +744,47 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements properties.testMode = TestMode.WEBTESTCLIENT } } + + @Issue('#880') + def 'should not generate a null statement when there is no content type in the response [#methodBuilderName]'() { + given: + Contract contractDsl = Contract.make { + description 'Should return 200' + request { + method POST() + url("/get") + headers { + contentType("application/json;charset=UTF-8") + } + } + response { + status OK() + body(file("getBody.json")) + } + } + methodBuilder() + when: + String test = singleTestGenerator(contractDsl) + SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) + then: + !test.contains('null') + test.contains('''.array("['array']")''') + where: + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "testng" | { properties.testFramework = TestFramework.TESTNG } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; + properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; + properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } + } + } diff --git a/spring-cloud-contract-verifier/src/test/resources/getBody.json b/spring-cloud-contract-verifier/src/test/resources/getBody.json new file mode 100644 index 0000000000..faf8d9b132 --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/resources/getBody.json @@ -0,0 +1,17 @@ +[ + { + "array": [ + "a", + "b" + ] + }, + { + "array": [ + "a", + "b" + ] + }, + { + "array": [] + } +] \ No newline at end of file