From 403d369b44737e670c350fe281ac174d0771525f Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Wed, 29 Jan 2020 19:42:14 +0100 Subject: [PATCH] Should work --- .../java/com/example/fraud/Application.java | 1 - .../stream/StubRunnerStreamConfiguration.java | 4 +- .../StubRunnerStubsPerConsumerSpec.groovy | 25 +++++++--- ...tubsPerConsumerWithConsumerNameSpec.groovy | 26 +++++++--- .../resources/application-streamconsumer.yml | 5 ++ .../StreamInputDestinationMessageSender.java | 24 +--------- ...treamOutputDestinationMessageReceiver.java | 27 +---------- ...Listener.java => BookDeletedListener.java} | 32 +++---------- .../com/example/BookReturnedListener.java | 47 +++++++++++++++++++ .../main/java/com/example/BookService.java | 26 ++++++---- .../src/main/java/com/example/DeleteSink.java | 32 ------------- .../example/StreamMessagingApplication.java | 13 +++-- .../src/main/resources/application.yml | 9 ++-- .../StreamMessagingApplicationSpec.groovy | 33 ++++++++----- .../moco/MocoHttpServerStubSpec.groovy | 6 +-- .../stream/StreamStubRunnerSpec.groovy | 7 ++- 16 files changed, 158 insertions(+), 159 deletions(-) create mode 100644 spring-cloud-contract-stub-runner/src/test/resources/application-streamconsumer.yml rename tests/samples-messaging-stream/src/main/java/com/example/{BookListener.java => BookDeletedListener.java} (53%) create mode 100644 tests/samples-messaging-stream/src/main/java/com/example/BookReturnedListener.java delete mode 100644 tests/samples-messaging-stream/src/main/java/com/example/DeleteSink.java diff --git a/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/Application.java b/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/Application.java index 136adffd3d..19ff0dd462 100644 --- a/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/Application.java +++ b/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/Application.java @@ -24,7 +24,6 @@ import org.springframework.context.annotation.Configuration; @Configuration @SpringBootApplication -@EnableBinding({ Source.class, MyProcessor.class }) public class Application { public static void main(String[] args) { diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/stream/StubRunnerStreamConfiguration.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/stream/StubRunnerStreamConfiguration.java index 23aa89e58c..4387b3c233 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/stream/StubRunnerStreamConfiguration.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/stream/StubRunnerStreamConfiguration.java @@ -36,7 +36,7 @@ import org.springframework.cloud.contract.spec.Contract; import org.springframework.cloud.contract.stubrunner.BatchStubRunner; import org.springframework.cloud.contract.stubrunner.StubConfiguration; import org.springframework.cloud.contract.stubrunner.messaging.integration.StubRunnerIntegrationConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; +import org.springframework.cloud.stream.binder.test.InputDestination; import org.springframework.cloud.stream.config.BindingProperties; import org.springframework.cloud.stream.config.BindingServiceProperties; import org.springframework.context.Lifecycle; @@ -56,7 +56,7 @@ import org.springframework.util.StringUtils; * @author Marcin Grzejszczak */ @Configuration(proxyBeanMethods = false) -@ConditionalOnClass({ IntegrationFlows.class, EnableBinding.class }) +@ConditionalOnClass({ IntegrationFlows.class, InputDestination.class }) @ConditionalOnProperty(name = "stubrunner.stream.enabled", havingValue = "true", matchIfMissing = true) @AutoConfigureBefore(StubRunnerIntegrationConfiguration.class) diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerStubsPerConsumerSpec.groovy b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerStubsPerConsumerSpec.groovy index 219f5dc836..a678de8c25 100644 --- a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerStubsPerConsumerSpec.groovy +++ b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerStubsPerConsumerSpec.groovy @@ -16,10 +16,13 @@ package org.springframework.cloud.contract.stubrunner.spring.cloud +import java.util.function.Function + import spock.lang.Specification import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.boot.autoconfigure.ImportAutoConfiguration import org.springframework.boot.test.context.SpringBootContextLoader import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.web.client.TestRestTemplate @@ -27,15 +30,14 @@ import org.springframework.cloud.contract.stubrunner.StubFinder import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties import org.springframework.cloud.contract.verifier.messaging.MessageVerifier -import org.springframework.cloud.stream.annotation.EnableBinding -import org.springframework.cloud.stream.messaging.Sink -import org.springframework.cloud.stream.messaging.Source +import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration +import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.core.env.Environment import org.springframework.http.ResponseEntity import org.springframework.messaging.Message +import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.ContextConfiguration - /** * @author Marcin Grzejszczak */ @@ -46,6 +48,7 @@ import org.springframework.test.context.ContextConfiguration repositoryRoot = "classpath:m2repo/repository/", stubsMode = StubRunnerProperties.StubsMode.REMOTE, stubsPerConsumer = true) +@ActiveProfiles("streamconsumer") class StubRunnerStubsPerConsumerSpec extends Specification { // end::test[] @@ -77,7 +80,7 @@ class StubRunnerStubsPerConsumerSpec extends Specification { Message receivedMessage = messaging.receive('output') and: receivedMessage != null - receivedMessage.payload == '''{"bookName":"foo_for_bar"}''' + receivedMessage.payload == '''{"bookName":"foo_for_bar"}'''.bytes receivedMessage.headers.get('BOOK-NAME') == 'foo_for_bar' } @@ -91,6 +94,14 @@ class StubRunnerStubsPerConsumerSpec extends Specification { @Configuration @EnableAutoConfiguration - @EnableBinding([Sink, Source]) - static class Config {} + @ImportAutoConfiguration(TestChannelBinderConfiguration.class) + static class Config { + @Bean + Function output() { + return { Object o -> + println(o) + return o + } + } + } } diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerStubsPerConsumerWithConsumerNameSpec.groovy b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerStubsPerConsumerWithConsumerNameSpec.groovy index 82b6df1bab..5850dfbff2 100644 --- a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerStubsPerConsumerWithConsumerNameSpec.groovy +++ b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerStubsPerConsumerWithConsumerNameSpec.groovy @@ -16,10 +16,13 @@ package org.springframework.cloud.contract.stubrunner.spring.cloud +import java.util.function.Function + import spock.lang.Specification import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.boot.autoconfigure.ImportAutoConfiguration import org.springframework.boot.test.context.SpringBootContextLoader import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.web.client.TestRestTemplate @@ -27,15 +30,14 @@ import org.springframework.cloud.contract.stubrunner.StubFinder import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties import org.springframework.cloud.contract.verifier.messaging.MessageVerifier -import org.springframework.cloud.stream.annotation.EnableBinding -import org.springframework.cloud.stream.messaging.Sink -import org.springframework.cloud.stream.messaging.Source +import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration +import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.core.env.Environment import org.springframework.http.ResponseEntity import org.springframework.messaging.Message +import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.ContextConfiguration - /** * @author Marcin Grzejszczak */ @@ -47,6 +49,7 @@ import org.springframework.test.context.ContextConfiguration consumerName = "foo-consumer", stubsMode = StubRunnerProperties.StubsMode.REMOTE, stubsPerConsumer = true) +@ActiveProfiles("streamconsumer") class StubRunnerStubsPerConsumerWithConsumerNameSpec extends Specification { // end::test[] @@ -56,6 +59,7 @@ class StubRunnerStubsPerConsumerWithConsumerNameSpec extends Specification { Environment environment @Autowired MessageVerifier> messaging + TestRestTemplate template = new TestRestTemplate() def 'should start http stub servers for foo-consumer only'() { @@ -78,7 +82,7 @@ class StubRunnerStubsPerConsumerWithConsumerNameSpec extends Specification { Message receivedMessage = messaging.receive('output') and: receivedMessage != null - receivedMessage.payload == '''{"bookName":"foo_for_foo"}''' + receivedMessage.payload == '''{"bookName":"foo_for_foo"}'''.bytes receivedMessage.headers.get('BOOK-NAME') == 'foo_for_foo' } @@ -92,6 +96,14 @@ class StubRunnerStubsPerConsumerWithConsumerNameSpec extends Specification { @Configuration @EnableAutoConfiguration - @EnableBinding([Sink, Source]) - static class Config {} + @ImportAutoConfiguration(TestChannelBinderConfiguration.class) + static class Config { + @Bean + Function output() { + return { Object o -> + println(o) + return o + } + } + } } diff --git a/spring-cloud-contract-stub-runner/src/test/resources/application-streamconsumer.yml b/spring-cloud-contract-stub-runner/src/test/resources/application-streamconsumer.yml new file mode 100644 index 0000000000..cd98425cb2 --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/test/resources/application-streamconsumer.yml @@ -0,0 +1,5 @@ +spring.cloud.function.definition: output +spring.cloud.stream.bindings.output-in-0.destination: output +spring.cloud.stream.bindings.output-in-0.contentType: application/json +spring.cloud.stream.bindings.output-out-0.destination: output +spring.cloud.stream.bindings.output-out-0.contentType: application/json \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/stream/StreamInputDestinationMessageSender.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/stream/StreamInputDestinationMessageSender.java index 2b4fd94afe..2d66586d35 100644 --- a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/stream/StreamInputDestinationMessageSender.java +++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/stream/StreamInputDestinationMessageSender.java @@ -16,19 +16,15 @@ package org.springframework.cloud.contract.verifier.messaging.stream; -import java.util.Arrays; import java.util.Map; -import java.util.stream.Collectors; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.cloud.contract.verifier.messaging.MessageVerifierSender; import org.springframework.cloud.stream.binder.test.InputDestination; -import org.springframework.cloud.stream.function.StreamFunctionProperties; import org.springframework.context.ApplicationContext; import org.springframework.messaging.Message; -import org.springframework.util.StringUtils; /** * @author Marcin Grzejszczak @@ -56,12 +52,7 @@ class StreamInputDestinationMessageSender implements MessageVerifierSender> { @@ -47,13 +43,8 @@ class StreamOutputDestinationMessageReceiver try { OutputDestination outputDestination = this.context .getBean(OutputDestination.class); - StreamFunctionProperties streamFunctionProperties = this.context - .getBean(StreamFunctionProperties.class); - int indexOfDestination = StringUtils - .isEmpty(streamFunctionProperties.getDefinition()) ? 0 - : indexOfDestination(streamFunctionProperties, destination); return outputDestination.receive(timeUnit.toMillis(timeout), - indexOfDestination); + destination); } catch (Exception e) { log.error("Exception occurred while trying to read a message from " @@ -62,22 +53,6 @@ class StreamOutputDestinationMessageReceiver } } - private int indexOfDestination(StreamFunctionProperties streamFunctionProperties, - String destination) { - String[] split = streamFunctionProperties.getDefinition().split(";"); - if (split.length == 1) { - return 0; - } - int indexOfDestination = Arrays.stream(split).map(String::toLowerCase) - .collect(Collectors.toList()).indexOf(destination.toLowerCase()); - if (indexOfDestination == -1) { - throw new IllegalStateException("Destination with name [" + destination - + "] not found in the function definitions [" - + streamFunctionProperties.getDefinition() + "]"); - } - return indexOfDestination; - } - @Override public Message receive(String destination) { return receive(destination, 5, TimeUnit.SECONDS); diff --git a/tests/samples-messaging-stream/src/main/java/com/example/BookListener.java b/tests/samples-messaging-stream/src/main/java/com/example/BookDeletedListener.java similarity index 53% rename from tests/samples-messaging-stream/src/main/java/com/example/BookListener.java rename to tests/samples-messaging-stream/src/main/java/com/example/BookDeletedListener.java index 54c97e7953..c97561db6a 100644 --- a/tests/samples-messaging-stream/src/main/java/com/example/BookListener.java +++ b/tests/samples-messaging-stream/src/main/java/com/example/BookDeletedListener.java @@ -17,48 +17,28 @@ package com.example; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.messaging.Sink; -import org.springframework.cloud.stream.messaging.Source; -import org.springframework.messaging.support.MessageBuilder; import org.springframework.stereotype.Component; -@Component -public class BookListener { +@Component("bookDeleted") +public class BookDeletedListener implements Consumer { - private static final Logger log = LoggerFactory.getLogger(BookListener.class); + private static final Logger log = LoggerFactory.getLogger(BookDeletedListener.class); public AtomicBoolean bookSuccessfulyDeleted = new AtomicBoolean(false); - @Autowired - private Source source; - /** * Scenario for "should generate tests triggered by a message": client side: if sends * a message to input.messageFrom then message will be sent to output.messageFrom * server side: will send a message to input, verify the message contents and await * upon receiving message on the output messageFrom */ - @StreamListener(Sink.INPUT) - public void returnBook(BookReturned bookReturned) { - log.info("Returning book " + bookReturned); - this.source.output().send(MessageBuilder.withPayload(bookReturned) - .setHeader("BOOK-NAME", bookReturned.bookName).build()); - } - - /** - * Scenario for "should generate tests triggered by a message": client side: if sends - * a message to input.messageFrom then message will be sent to output.messageFrom - * server side: will send a message to input, verify the message contents and await - * upon receiving message on the output messageFrom - */ - @StreamListener(DeleteSink.MYINPUT) - public void bookDeleted(BookDeleted bookDeleted) { + @Override + public void accept(BookDeleted bookDeleted) { log.info("Deleting book " + bookDeleted); // ... doing some work this.bookSuccessfulyDeleted.set(true); diff --git a/tests/samples-messaging-stream/src/main/java/com/example/BookReturnedListener.java b/tests/samples-messaging-stream/src/main/java/com/example/BookReturnedListener.java new file mode 100644 index 0000000000..d60631a9c1 --- /dev/null +++ b/tests/samples-messaging-stream/src/main/java/com/example/BookReturnedListener.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example; + +import java.util.function.Function; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.messaging.Message; +import org.springframework.messaging.support.MessageBuilder; +import org.springframework.stereotype.Component; + +@Component("bookReturned") +public class BookReturnedListener + implements Function> { + + private static final Logger log = LoggerFactory.getLogger(BookReturnedListener.class); + + /** + * Scenario for "should generate tests triggered by a message": client side: if sends + * a message to input.messageFrom then message will be sent to output.messageFrom + * server side: will send a message to input, verify the message contents and await + * upon receiving message on the output messageFrom + */ + @Override + public Message apply(BookReturned bookReturned) { + log.info("Got the book " + bookReturned); + return MessageBuilder.withPayload(bookReturned) + .setHeader("BOOK-NAME", bookReturned.bookName).build(); + } + +} diff --git a/tests/samples-messaging-stream/src/main/java/com/example/BookService.java b/tests/samples-messaging-stream/src/main/java/com/example/BookService.java index 60ee1748a3..07bcf10a36 100644 --- a/tests/samples-messaging-stream/src/main/java/com/example/BookService.java +++ b/tests/samples-messaging-stream/src/main/java/com/example/BookService.java @@ -16,24 +16,27 @@ package com.example; +import java.util.function.Supplier; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import reactor.core.publisher.EmitterProcessor; +import reactor.core.publisher.Flux; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.stream.messaging.Source; import org.springframework.integration.support.MessageBuilder; +import org.springframework.messaging.Message; import org.springframework.stereotype.Service; -@Service -public class BookService { +@Service("bookSender") +public class BookService implements Supplier>> { private static final Logger log = LoggerFactory.getLogger(BookService.class); - private final Source source; + private final EmitterProcessor> bookReturnedEmitterProcessor; - @Autowired - public BookService(Source source) { - this.source = source; + public BookService( + EmitterProcessor> bookReturnedEmitterProcessor) { + this.bookReturnedEmitterProcessor = bookReturnedEmitterProcessor; } /** @@ -46,8 +49,13 @@ public class BookService { */ public void returnBook(BookReturned bookReturned) { log.info("Returning book " + bookReturned); - this.source.output().send(MessageBuilder.withPayload(bookReturned) + this.bookReturnedEmitterProcessor.onNext(MessageBuilder.withPayload(bookReturned) .setHeader("BOOK-NAME", bookReturned.bookName).build()); } + @Override + public Flux> get() { + return this.bookReturnedEmitterProcessor; + } + } diff --git a/tests/samples-messaging-stream/src/main/java/com/example/DeleteSink.java b/tests/samples-messaging-stream/src/main/java/com/example/DeleteSink.java deleted file mode 100644 index 3e56082ef6..0000000000 --- a/tests/samples-messaging-stream/src/main/java/com/example/DeleteSink.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2013-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.example; - -import org.springframework.cloud.stream.annotation.Input; -import org.springframework.messaging.SubscribableChannel; - -/** - * @author Marcin Grzejszczak - */ -interface DeleteSink { - - String MYINPUT = "delete"; - - @Input(DeleteSink.MYINPUT) - SubscribableChannel delete(); - -} diff --git a/tests/samples-messaging-stream/src/main/java/com/example/StreamMessagingApplication.java b/tests/samples-messaging-stream/src/main/java/com/example/StreamMessagingApplication.java index 4b1bfd1018..1f2bf8e759 100644 --- a/tests/samples-messaging-stream/src/main/java/com/example/StreamMessagingApplication.java +++ b/tests/samples-messaging-stream/src/main/java/com/example/StreamMessagingApplication.java @@ -16,18 +16,23 @@ package com.example; +import reactor.core.publisher.EmitterProcessor; + import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.messaging.Sink; -import org.springframework.cloud.stream.messaging.Source; +import org.springframework.context.annotation.Bean; +import org.springframework.messaging.Message; @SpringBootApplication -@EnableBinding({ Source.class, DeleteSink.class, Sink.class }) class StreamMessagingApplication { public static void main(String[] args) { SpringApplication.run(StreamMessagingApplication.class, args); } + @Bean + EmitterProcessor> bookReturnedEmitterProcessor() { + return EmitterProcessor.create(); + } + } diff --git a/tests/samples-messaging-stream/src/main/resources/application.yml b/tests/samples-messaging-stream/src/main/resources/application.yml index a8ef4c8ab2..2c171186c9 100644 --- a/tests/samples-messaging-stream/src/main/resources/application.yml +++ b/tests/samples-messaging-stream/src/main/resources/application.yml @@ -1,4 +1,5 @@ -spring.cloud.stream.bindings.myinput.destination: inputDestination -spring.cloud.stream.bindings.myinput.contentType: application/json -spring.cloud.stream.bindings.output.destination: sentTo -spring.cloud.stream.bindings.output.contentType: application/json +spring.cloud.function.definition: bookReturned;bookSender;bookDeleted +spring.cloud.stream.bindings.bookSender-out-0.destination: inputDestination +spring.cloud.stream.bindings.bookReturned-in-0.destination: inputDestination +spring.cloud.stream.bindings.bookReturned-out-0.destination: bookReturned +spring.cloud.stream.bindings.bookDeleted-in-0.destination: bookDeleted diff --git a/tests/samples-messaging-stream/src/test/groovy/com/example/StreamMessagingApplicationSpec.groovy b/tests/samples-messaging-stream/src/test/groovy/com/example/StreamMessagingApplicationSpec.groovy index 59aaf03a92..d07277f342 100644 --- a/tests/samples-messaging-stream/src/test/groovy/com/example/StreamMessagingApplicationSpec.groovy +++ b/tests/samples-messaging-stream/src/test/groovy/com/example/StreamMessagingApplicationSpec.groovy @@ -24,12 +24,16 @@ import com.toomuchcoding.jsonassert.JsonAssertion import spock.lang.Specification import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.boot.autoconfigure.ImportAutoConfiguration import org.springframework.boot.test.context.SpringBootContextLoader import org.springframework.boot.test.context.SpringBootTest import org.springframework.cloud.contract.spec.Contract import org.springframework.cloud.contract.verifier.messaging.MessageVerifier import org.springframework.cloud.contract.verifier.messaging.boot.AutoConfigureMessageVerifier import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper +import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration +import org.springframework.context.annotation.Configuration import org.springframework.messaging.Message import org.springframework.test.context.ContextConfiguration @@ -37,7 +41,7 @@ import org.springframework.test.context.ContextConfiguration * SPIKE ON TESTS FROM NOTES IN MessagingSpec */ // Context configuration would end up in base class -@ContextConfiguration(classes = [StreamMessagingApplication], loader = SpringBootContextLoader) +@ContextConfiguration(classes = [Config, StreamMessagingApplication], loader = SpringBootContextLoader) @SpringBootTest(properties = "debug=true") @AutoConfigureMessageVerifier class StreamMessagingApplicationSpec extends Specification { @@ -55,7 +59,7 @@ class StreamMessagingApplicationSpec extends Specification { triggeredBy('bookReturnedTriggered()') } outputMessage { - sentTo('output') + sentTo('bookReturned') body('''{ "bookName" : "foo" }''') headers { header('BOOK-NAME', 'foo') @@ -66,7 +70,7 @@ class StreamMessagingApplicationSpec extends Specification { when: bookReturnedTriggered() then: - def response = contractVerifierMessaging.receive('output') + def response = contractVerifierMessaging.receive('bookReturned') response.headers.get('BOOK-NAME') == 'foo' and: DocumentContext parsedJson = JsonPath. @@ -79,7 +83,7 @@ class StreamMessagingApplicationSpec extends Specification { def dsl = Contract.make { label 'some_label' input { - messageFrom('input') + messageFrom('inputDestination') messageBody([ bookName: 'foo' ]) @@ -88,7 +92,7 @@ class StreamMessagingApplicationSpec extends Specification { } } outputMessage { - sentTo('output') + sentTo('bookReturned') body([ bookName: 'foo' ]) @@ -103,9 +107,9 @@ class StreamMessagingApplicationSpec extends Specification { when: contractVerifierMessaging.send( contractVerifierObjectMapper.writeValueAsString([bookName: 'foo']), - [sample: 'header'], 'input') + [sample: 'header'], 'inputDestination') then: - def response = contractVerifierMessaging.receive('output') + def response = contractVerifierMessaging.receive('bookReturned') response.headers.get('BOOK-NAME') == 'foo' and: DocumentContext parsedJson = JsonPath. @@ -118,7 +122,7 @@ class StreamMessagingApplicationSpec extends Specification { def dsl = Contract.make { label 'some_label' input { - messageFrom('delete') + messageFrom("bookDeleted") messageBody([ bookName: 'foo' ]) @@ -134,7 +138,7 @@ class StreamMessagingApplicationSpec extends Specification { when: contractVerifierMessaging. send(contractVerifierObjectMapper.writeValueAsString([bookName: 'foo']), - [sample: 'header'], 'delete') + [sample: 'header'], "bookDeleted") then: noExceptionThrown() bookWasDeleted() @@ -145,13 +149,20 @@ class StreamMessagingApplicationSpec extends Specification { @Autowired BookService bookService @Autowired - BookListener bookListener + BookDeletedListener bookDeletedListener void bookReturnedTriggered() { bookService.returnBook(new BookReturned("foo")) } void bookWasDeleted() { - assert bookListener.bookSuccessfulyDeleted.get() + assert bookDeletedListener.bookSuccessfulyDeleted.get() + } + + @Configuration + @EnableAutoConfiguration + @ImportAutoConfiguration(TestChannelBinderConfiguration) + static class Config { + } } diff --git a/tests/spring-cloud-contract-stub-runner-moco/src/test/groovy/org/springframework/cloud/contract/stubrunner/provider/moco/MocoHttpServerStubSpec.groovy b/tests/spring-cloud-contract-stub-runner-moco/src/test/groovy/org/springframework/cloud/contract/stubrunner/provider/moco/MocoHttpServerStubSpec.groovy index 1bc248bc21..0b28fec79b 100644 --- a/tests/spring-cloud-contract-stub-runner-moco/src/test/groovy/org/springframework/cloud/contract/stubrunner/provider/moco/MocoHttpServerStubSpec.groovy +++ b/tests/spring-cloud-contract-stub-runner-moco/src/test/groovy/org/springframework/cloud/contract/stubrunner/provider/moco/MocoHttpServerStubSpec.groovy @@ -20,20 +20,20 @@ import spock.lang.Specification import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.boot.autoconfigure.ImportAutoConfiguration import org.springframework.boot.test.context.SpringBootContextLoader import org.springframework.boot.test.context.SpringBootTest import org.springframework.cloud.contract.stubrunner.StubFinder import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties -import org.springframework.cloud.stream.annotation.EnableBinding import org.springframework.cloud.stream.annotation.StreamListener +import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration import org.springframework.cloud.stream.messaging.Sink import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.stereotype.Component import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.ContextConfiguration - /** * @author Marcin Grzejszczak */ @@ -75,7 +75,7 @@ class MocoHttpServerStubSpec extends Specification { @Configuration @EnableAutoConfiguration - @EnableBinding(Sink.class) + @ImportAutoConfiguration(TestChannelBinderConfiguration.class) static class MocoConfig { @Bean diff --git a/tests/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy b/tests/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy index 780fccb474..759d5ecc37 100644 --- a/tests/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy +++ b/tests/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy @@ -25,6 +25,7 @@ import spock.lang.Specification import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.boot.autoconfigure.ImportAutoConfiguration import org.springframework.boot.test.context.SpringBootContextLoader import org.springframework.boot.test.context.SpringBootTest import org.springframework.cloud.contract.spec.Contract @@ -32,9 +33,7 @@ import org.springframework.cloud.contract.stubrunner.StubFinder import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner import org.springframework.cloud.contract.verifier.messaging.MessageVerifier import org.springframework.cloud.contract.verifier.messaging.boot.AutoConfigureMessageVerifier -import org.springframework.cloud.stream.annotation.EnableBinding -import org.springframework.cloud.stream.messaging.Sink -import org.springframework.cloud.stream.messaging.Source +import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration import org.springframework.context.annotation.Configuration import org.springframework.messaging.Message import org.springframework.test.context.ContextConfiguration @@ -221,7 +220,7 @@ class StreamStubRunnerSpec extends Specification { // end::sample_dsl_3[] - @EnableBinding([Sink, Source]) + @ImportAutoConfiguration(TestChannelBinderConfiguration.class) @Configuration @EnableAutoConfiguration protected static class Config {}