Should work
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Message<?>> 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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<Messa
|
||||
try {
|
||||
InputDestination inputDestination = this.context
|
||||
.getBean(InputDestination.class);
|
||||
StreamFunctionProperties streamFunctionProperties = this.context
|
||||
.getBean(StreamFunctionProperties.class);
|
||||
int indexOfDestination = StringUtils
|
||||
.isEmpty(streamFunctionProperties.getDefinition()) ? 0
|
||||
: indexOfDestination(streamFunctionProperties, destination);
|
||||
inputDestination.send(message, indexOfDestination);
|
||||
inputDestination.send(message, destination);
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("Exception occurred while trying to send a message [" + message
|
||||
@@ -70,17 +61,4 @@ class StreamInputDestinationMessageSender implements MessageVerifierSender<Messa
|
||||
}
|
||||
}
|
||||
|
||||
private int indexOfDestination(StreamFunctionProperties streamFunctionProperties,
|
||||
String destination) {
|
||||
String[] split = streamFunctionProperties.getDefinition().split(";");
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,19 +16,15 @@
|
||||
|
||||
package org.springframework.cloud.contract.verifier.messaging.stream;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.messaging.MessageVerifierReceiver;
|
||||
import org.springframework.cloud.stream.binder.test.OutputDestination;
|
||||
import org.springframework.cloud.stream.function.StreamFunctionProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
class StreamOutputDestinationMessageReceiver
|
||||
implements MessageVerifierReceiver<Message<?>> {
|
||||
@@ -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);
|
||||
|
||||
@@ -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<BookDeleted> {
|
||||
|
||||
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);
|
||||
@@ -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<BookReturned, Message<BookReturned>> {
|
||||
|
||||
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<BookReturned> apply(BookReturned bookReturned) {
|
||||
log.info("Got the book " + bookReturned);
|
||||
return MessageBuilder.withPayload(bookReturned)
|
||||
.setHeader("BOOK-NAME", bookReturned.bookName).build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<Flux<Message<BookReturned>>> {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(BookService.class);
|
||||
|
||||
private final Source source;
|
||||
private final EmitterProcessor<Message<BookReturned>> bookReturnedEmitterProcessor;
|
||||
|
||||
@Autowired
|
||||
public BookService(Source source) {
|
||||
this.source = source;
|
||||
public BookService(
|
||||
EmitterProcessor<Message<BookReturned>> 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<Message<BookReturned>> get() {
|
||||
return this.bookReturnedEmitterProcessor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
@@ -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<Message<BookReturned>> bookReturnedEmitterProcessor() {
|
||||
return EmitterProcessor.create();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
Reference in New Issue
Block a user