From d683d3d6f06c8653d9c834fedab620942e1015cd Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Thu, 17 Nov 2016 12:55:48 +0100 Subject: [PATCH] Added regex support for text based response without this change any assertion on a text based response wouldn't work with this change we start doing regex checks fixes #150 --- .../JUnitMessagingMethodBodyBuilder.groovy | 21 ++++++++++++---- .../builder/JUnitMethodBodyBuilder.groovy | 16 ++++++++++++- .../verifier/builder/MethodBodyBuilder.groovy | 24 ++++++++++++++----- .../MockMvcJUnitMethodBodyBuilder.groovy | 10 ++++++++ .../SpockMessagingMethodBodyBuilder.groovy | 12 +++++++++- ...kMethodRequestProcessingBodyBuilder.groovy | 16 ++++++++++++- .../JaxRsClientMethodBuilderSpec.groovy | 23 ++++++++++++++++++ .../MockMvcMethodBodyBuilderSpec.groovy | 23 ++++++++++++++++++ 8 files changed, 132 insertions(+), 13 deletions(-) diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMessagingMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMessagingMethodBodyBuilder.groovy index b1efd1c635..78c8430f74 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMessagingMethodBodyBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMessagingMethodBodyBuilder.groovy @@ -56,9 +56,19 @@ class JUnitMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder { return "contractVerifierMessaging.send(inputMessage, \"${request.messageFrom.serverValue}\")" } + @Override + protected String getResponseBodyPropertyComparisonString(String property, Object value) { + return "" + } + @Override protected String getResponseBodyPropertyComparisonString(String property, String value) { - return "responseBody$property == \"${value}\"" + return "" + } + + @Override + protected String getResponseBodyPropertyComparisonString(String property, Pattern value) { + return "" } @Override @@ -158,7 +168,7 @@ class JUnitMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder { @Override protected String getBodyString(String bodyAsString) { - return '' + return "" } @Override @@ -172,11 +182,11 @@ class JUnitMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder { } protected String convertHeaderComparison(String headerValue) { - return " == '$headerValue'" + return "" } protected String convertHeaderComparison(Pattern headerValue) { - return "==~ java.util.regex.Pattern.compile('$headerValue')" + return "" } protected String createHeaderComparison(Object headerValue) { @@ -189,4 +199,7 @@ class JUnitMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder { return "matches(\"$escapedHeader\");" } + private String patternText(Pattern value) { + return "==~ java.util.regex.Pattern.compile('$value')" + } } 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 e74fbd4e57..553b13b6b0 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 @@ -71,6 +71,16 @@ abstract class JUnitMethodBodyBuilder extends RequestProcessingMethodBodyBuilder return "assertThat(responseBody${property}).isEqualTo(\"${value}\")" } + @Override + protected String getResponseBodyPropertyComparisonString(String property, Object value) { + return getResponseBodyPropertyComparisonString(property, value as String) + } + + @Override + protected String getResponseBodyPropertyComparisonString(String property, Pattern value) { + return "assertThat(responseBody${property}).${buildEscapedMatchesMethod(value)}" + } + @Override protected void processBodyElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { blockBuilder.addLine("${exec.insertValue("parsedJson.read(\"\\\$$property\")")};") @@ -149,8 +159,12 @@ abstract class JUnitMethodBodyBuilder extends RequestProcessingMethodBodyBuilder } protected String createHeaderComparison(Pattern headerValue) { + return buildEscapedMatchesMethod(headerValue) + ";" + } + + private String buildEscapedMatchesMethod(Pattern headerValue) { String escapedHeader = convertUnicodeEscapesIfRequired("$headerValue") - return "matches(\"$escapedHeader\");" + return "matches(\"$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 f22349c587..af40d02fc6 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 @@ -75,10 +75,22 @@ abstract class MethodBodyBuilder { /** * Builds the code that for the given {@code property} will compare it to - * the given {@code value} + * the given Object {@code value} + */ + protected abstract String getResponseBodyPropertyComparisonString(String property, Object value) + + /** + * Builds the code that for the given {@code property} will compare it to + * the given String {@code value} */ protected abstract String getResponseBodyPropertyComparisonString(String property, String value) + /** + * Builds the code that for the given {@code property} will match it to + * the given regular expression {@code value} + */ + protected abstract String getResponseBodyPropertyComparisonString(String property, Pattern value) + /** * Appends to the {@link BlockBuilder} the assertion for the given body element */ @@ -263,7 +275,7 @@ abstract class MethodBodyBuilder { // TODO xml validation } else { bb.addLine(getSimpleResponseBodyString(getResponseAsString())) - processText(bb, "", convertedResponseBody as String) + processText(bb, "", convertedResponseBody) addColonIfRequired(bb) } } @@ -286,10 +298,10 @@ abstract class MethodBodyBuilder { /** * Appends to {@link BlockBuilder} processing of the given String value. */ - protected void processText(BlockBuilder blockBuilder, String property, String value) { - if (value.startsWith('$')) { - value = stripFirstChar(value).replaceAll('\\$value', "responseBody$property") - blockBuilder.addLine(value) + protected void processText(BlockBuilder blockBuilder, String property, Object value) { + if (value instanceof String && value.startsWith('$')) { + String newValue = stripFirstChar(value).replaceAll('\\$value', "responseBody$property") + blockBuilder.addLine(newValue) addColonIfRequired(blockBuilder) } else { blockBuilder.addLine(getResponseBodyPropertyComparisonString(property, value)) diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcJUnitMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcJUnitMethodBodyBuilder.groovy index d4556732aa..622c6bde79 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcJUnitMethodBodyBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcJUnitMethodBodyBuilder.groovy @@ -52,6 +52,16 @@ class MockMvcJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder { } } + @Override + protected String getResponseBodyPropertyComparisonString(String property, Object value) { + return null + } + + @Override + protected String getResponseBodyPropertyComparisonString(String property, Pattern value) { + return null + } + @Override protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) { blockBuilder.addLine("assertThat(response.header(\"$property\")).${createHeaderComparison(value)}") diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingMethodBodyBuilder.groovy index 962b56b166..49e4fde0a2 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingMethodBodyBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingMethodBodyBuilder.groovy @@ -51,6 +51,11 @@ class SpockMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder { return "responseBody$property == \"${value}\"" } + @Override + protected String getResponseBodyPropertyComparisonString(String property, Pattern value) { + return null + } + @Override protected void processBodyElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { blockBuilder.addLine("${exec.insertValue("parsedJson.read('\\\$$property')")}") @@ -108,9 +113,14 @@ class SpockMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder { return blockBuilder } + @Override + protected String getResponseBodyPropertyComparisonString(String property, Object value) { + return "" + } + @Override protected String getPropertyInListString(String property, Integer listIndex) { - "$property[$listIndex]" ?: '' + return "$property[$listIndex]" ?: '' } @Override diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodRequestProcessingBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodRequestProcessingBodyBuilder.groovy index 36d63123c4..a33a29a350 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodRequestProcessingBodyBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodRequestProcessingBodyBuilder.groovy @@ -50,6 +50,16 @@ abstract class SpockMethodRequestProcessingBodyBuilder extends RequestProcessing return "responseBody$property == \"${value}\"" } + @Override + protected String getResponseBodyPropertyComparisonString(String property, Object value) { + return getResponseBodyPropertyComparisonString(property, value as String) + } + + @Override + protected String getResponseBodyPropertyComparisonString(String property, Pattern value) { + return "responseBody$property ${patternComparison(value)}" + } + @Override protected void processBodyElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { blockBuilder.addLine("${exec.insertValue("parsedJson.read('\\\$$property')")}") @@ -129,7 +139,11 @@ abstract class SpockMethodRequestProcessingBodyBuilder extends RequestProcessing } protected String convertHeaderComparison(Pattern headerValue) { - return "==~ java.util.regex.Pattern.compile('$headerValue')" + return patternComparison(headerValue) + } + + private String patternComparison(Pattern pattern) { + return "==~ java.util.regex.Pattern.compile('$pattern')" } } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy index 4e1132539c..99fc611670 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy @@ -743,6 +743,29 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub test.contains('assertThatRejectionReasonIsNull(parsedJson.read("$.get("rejectionReason").title"));') } + @Issue('#150') + def "should support body matching in response"() { + given: + Contract contractDsl = Contract.make { + request { + method 'GET' + url '/get' + } + response { + status 200 + status 200 + body(value(stub("HELLO FROM STUB"), server(regex(".*")))) + } + } + MethodBodyBuilder builder = new JaxRsClientJUnitMethodBodyBuilder(contractDsl, properties) + BlockBuilder blockBuilder = new BlockBuilder(" ") + when: + builder.then(blockBuilder) + def test = blockBuilder.toString() + then: + test.contains("assertThat(responseBody).matches(\".*\");") + } + private String stripped(String string) { return string.stripMargin().stripIndent().replace('\t', '').replace('\n', '').replace(' ','') } 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 9fcb64324b..f40d81271a 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 @@ -1622,4 +1622,27 @@ World.'''""" test.contains('.header("authorization", getOAuthTokenHeader())') } + @Issue('#150') + def "should support body matching in response"() { + given: + Contract contractDsl = Contract.make { + request { + method 'GET' + url '/get' + } + response { + status 200 + status 200 + body(value(stub("HELLO FROM STUB"), server(regex(".*")))) + } + } + MethodBodyBuilder builder = new MockMvcSpockMethodRequestProcessingBodyBuilder(contractDsl, properties) + BlockBuilder blockBuilder = new BlockBuilder(" ") + when: + builder.then(blockBuilder) + def test = blockBuilder.toString() + then: + test.contains("responseBody ==~ java.util.regex.Pattern.compile('.*')") + } + }