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 0ba07804d8..e88db6986f 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 @@ -41,6 +41,7 @@ import static org.springframework.cloud.contract.verifier.config.TestFramework.J * * @author Marcin Grzejszczak * @author Jakub Kubrynski, codearte.io + * @author Tim Ysewyn * * @since 1.0.0 */ @@ -244,11 +245,7 @@ class JUnitMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder { } protected String createHeaderComparison(Pattern headerValue) { - String escapedJavaHeader = escapeJava(headerValue.toString()) + String escapedJavaHeader = escapeJava(headerValue.pattern()) return "matches(\"$escapedJavaHeader\");" } - - 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/SpockMessagingMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingMethodBodyBuilder.groovy index 1211f78df1..1c2777587d 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 @@ -30,8 +30,12 @@ import org.springframework.cloud.contract.verifier.config.ContractVerifierConfig import org.springframework.cloud.contract.verifier.util.MapConverter import java.util.regex.Pattern + +import static org.apache.commons.text.StringEscapeUtils.escapeJava + /** * @author Jakub Kubrynski, codearte.io + * @author Tim Ysewyn */ @PackageScope @TypeChecked @@ -226,7 +230,8 @@ class SpockMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder { } protected String convertHeaderComparison(Pattern headerValue) { - return "==~ java.util.regex.Pattern.compile('$headerValue')" + String converted = escapeJava(convertUnicodeEscapesIfRequired(headerValue.pattern())) + return "==~ java.util.regex.Pattern.compile('${converted}')" } // #273 - should escape $ for Groovy since it will try to make it a GString diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy index 3cc4e121ec..311c079ff8 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy @@ -824,4 +824,63 @@ Contract.make { stripped(test) == stripped(expectedMsg) } + @Issue('#620') + def "should generate tests with message headers containing regular expression which compile for [#methodBuilderName]"() { + given: + Contract contractDsl = Contract.make { + label 'shouldPublishMessage' + // input to the contract + input { + // the contract will be triggered by a method + triggeredBy('foo()') + } + // output message of the contract + outputMessage { + // destination to which the output message will be sent + sentTo('messageExchange') + // the body of the output message + body([ + "field": "value" + ]) + headers { + header('Authorization', value(regex('Bearer [A-Za-z0-9\\-\\._~\\+\\/]+=*'))) + } + } + } + MethodBodyBuilder builder = methodBuilder(contractDsl) + BlockBuilder blockBuilder = new BlockBuilder(" ") + when: + builder.appendTo(blockBuilder) + def test = blockBuilder.toString() + then: + !test.contains('cursor') + !test.contains('REGEXP>>') + test == expectedTest + where: + methodBuilderName | methodBuilder | expectedTest + "SpockMessagingMethodBodyBuilder" | { Contract dsl -> new SpockMessagingMethodBodyBuilder(dsl, properties) } | ''' when: + foo() + + then: + ContractVerifierMessage response = contractVerifierMessaging.receive('messageExchange') + assert response != null + response.getHeader('Authorization')?.toString() ==~ java.util.regex.Pattern.compile('Bearer [A-Za-z0-9-._~+/]+=*') + and: + DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload)) + assertThatJson(parsedJson).field("['field']").isEqualTo("value") +''' + "JUnitMessagingMethodBodyBuilder" | { Contract dsl -> new JUnitMessagingMethodBodyBuilder(dsl, properties) } | ''' // when: + foo(); + + // then: + ContractVerifierMessage response = contractVerifierMessaging.receive("messageExchange"); + assertThat(response).isNotNull(); + assertThat(response.getHeader("Authorization")).isNotNull(); + assertThat(response.getHeader("Authorization").toString()).matches("Bearer [A-Za-z0-9\\\\-\\\\._~\\\\+\\\\/]+=*"); + // and: + DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); + assertThatJson(parsedJson).field("['field']").isEqualTo("value"); +''' + } + }