diff --git a/docs/src/main/asciidoc/verifier_contract.adoc b/docs/src/main/asciidoc/verifier_contract.adoc index d96dbf14ab..29044560df 100644 --- a/docs/src/main/asciidoc/verifier_contract.adoc +++ b/docs/src/main/asciidoc/verifier_contract.adoc @@ -863,6 +863,7 @@ following sections explain the differences: * <> * <> * <> +* <> [[contract-dsl-output-triggered-method]] ==== Output Triggered by a Method @@ -911,6 +912,14 @@ parts): include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=consumer_producer] ---- +[[contract-dsl-common]] +==== Common + +In the `input {}` or `outputMessage {}` section you can call `assertThat` with the name +of a `method` (e.g. `assertThatMessageIsOnTheQueue()`) that you have defined in the +base class or in a static import. Spring Cloud Pipelines will execute that method +in the genertaed test. + === Multiple Contracts in One File You can define multiple contracts in one file. Such a contract might resemble the 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 5681566294..dd528957eb 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 @@ -119,7 +119,7 @@ class JUnitMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder { @Override protected void validateResponseHeadersBlock(BlockBuilder bb) { - bb.addLine("""ContractVerifierMessage response = contractVerifierMessaging.receive("${outputMessage.sentTo.serverValue}");""") + bb.addLine("""ContractVerifierMessage response = contractVerifierMessaging.receive("${sentToValue(outputMessage.sentTo.serverValue)}");""") bb.addLine("""assertThat(response).isNotNull();""") outputMessage.headers?.executeForEachHeader { Header header -> processHeaderElement(bb, header.name, header.serverValue instanceof NotToEscapePattern ? @@ -128,6 +128,13 @@ class JUnitMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder { } } + private String sentToValue(Object sentTo) { + if (sentTo instanceof ExecutionProperty) { + return ((ExecutionProperty) sentTo).executionCommand + } + return '"' + sentTo.toString() + '"' + } + @Override protected String getResponseAsString() { return 'contractVerifierObjectMapper.writeValueAsString(response.getPayload())' 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 2cf0fc3732..123a72c760 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 @@ -96,13 +96,20 @@ class SpockMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder { @Override protected void validateResponseCodeBlock(BlockBuilder bb) { if (outputMessage) { - bb.addLine("""ContractVerifierMessage response = contractVerifierMessaging.receive('${outputMessage.sentTo.serverValue}')""") + bb.addLine("""ContractVerifierMessage response = contractVerifierMessaging.receive(${sentToValue(outputMessage.sentTo.serverValue)})""") bb.addLine("""assert response != null""") } else { bb.addLine('noExceptionThrown()') } } + private String sentToValue(Object sentTo) { + if (sentTo instanceof ExecutionProperty) { + return ((ExecutionProperty) sentTo).executionCommand + } + return "'" + sentTo.toString() + "'" + } + @Override protected void validateResponseHeadersBlock(BlockBuilder bb) { outputMessage.headers?.executeForEachHeader { Header header -> 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 ed0fd0e856..7bd6ec17ab 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 @@ -542,4 +542,91 @@ Contract.make { stripped(test) == stripped(expectedMsg) } + @Issue("440") + def "should generate tests with sentTo having a method execution for Spock"() { + given: + def contractDsl = + org.springframework.cloud.contract.spec.Contract.make { + label 'trigger_event' + + input { + triggeredBy('requestIsCalled()') + } + + outputMessage { + sentTo $(producer(execute("toString()")), consumer('topic.rateablequote')) + headers { + header('processId', value(producer(regex('[0-9]+')), consumer('123'))) + } + body([ + eventId: value(producer(regex('[0-9]+')), consumer('1')) + ]) + } + } + MethodBodyBuilder builder = new SpockMessagingMethodBodyBuilder(contractDsl, properties) + BlockBuilder blockBuilder = new BlockBuilder(" ") + when: + builder.appendTo(blockBuilder) + def test = blockBuilder.toString() + then: + String expectedMsg = + ''' + when: + requestIsCalled() + + then: + ContractVerifierMessage response = contractVerifierMessaging.receive(toString()) + assert response != null + response.getHeader('processId')?.toString() ==~ java.util.regex.Pattern.compile('[0-9]+') + and: + DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload)) + assertThatJson(parsedJson).field("['eventId']").matches("[0-9]+") +''' + stripped(test) == stripped(expectedMsg) + } + + @Issue("440") + def "should generate tests with sentTo having a method execution for JUnit"() { + given: + def contractDsl = + org.springframework.cloud.contract.spec.Contract.make { + label 'trigger_event' + + input { + triggeredBy('requestIsCalled()') + } + + outputMessage { + sentTo $(producer(execute("toString()")), consumer('topic.rateablequote')) + headers { + header('processId', value(producer(regex('[0-9]+')), consumer('123'))) + } + body([ + eventId: value(producer(regex('[0-9]+')), consumer('1')) + ]) + } + } + MethodBodyBuilder builder = new JUnitMessagingMethodBodyBuilder(contractDsl, properties) + BlockBuilder blockBuilder = new BlockBuilder(" ") + when: + builder.appendTo(blockBuilder) + def test = blockBuilder.toString() + then: + String expectedMsg = + ''' + // when: + requestIsCalled(); + + // then: + ContractVerifierMessage response = contractVerifierMessaging.receive(toString()); + assertThat(response).isNotNull(); + assertThat(response.getHeader("processId")).isNotNull(); + assertThat(response.getHeader("processId").toString()).matches("[0-9]+"); + // and: + DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); + assertThatJson(parsedJson).field("['eventId']").matches("[0-9]+"); +''' + stripped(test) == stripped(expectedMsg) + } + }