XD-3381: Provide test support for modules
This commit is contained in:
committed by
David Turanski
parent
6d01a2ef79
commit
e2497efa39
24
pom.xml
24
pom.xml
@@ -9,7 +9,7 @@
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-build</artifactId>
|
||||
<version>1.1.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath />
|
||||
<relativePath/>
|
||||
</parent>
|
||||
<scm>
|
||||
<url>https://github.com/spring-cloud/spring-cloud-stream</url>
|
||||
@@ -20,6 +20,7 @@
|
||||
<properties>
|
||||
<java.version>1.7</java.version>
|
||||
<spring-boot.version>1.3.0.BUILD-SNAPSHOT</spring-boot.version>
|
||||
<spring-framework.version>4.2.1.BUILD-SNAPSHOT</spring-framework.version>
|
||||
<spring-integration.version>4.2.0.BUILD-SNAPSHOT</spring-integration.version>
|
||||
<spring-cloud-lattice.version>1.1.0.BUILD-SNAPSHOT</spring-cloud-lattice.version>
|
||||
</properties>
|
||||
@@ -30,6 +31,7 @@
|
||||
<module>spring-cloud-stream-module-launcher</module>
|
||||
<module>spring-cloud-stream-samples</module>
|
||||
<module>docs</module>
|
||||
<module>spring-cloud-stream-test-support</module>
|
||||
</modules>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
@@ -67,6 +69,11 @@
|
||||
<artifactId>spring-cloud-stream-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binder-spi</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binder-local</artifactId>
|
||||
@@ -82,11 +89,6 @@
|
||||
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binder-spi</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binder-test</artifactId>
|
||||
@@ -97,6 +99,16 @@
|
||||
<artifactId>spring-cloud-stream-module-launcher</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-test-support</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-messaging</artifactId>
|
||||
<version>${spring-framework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-core</artifactId>
|
||||
|
||||
41
spring-cloud-stream-test-support/pom.xml
Normal file
41
spring-cloud-stream-test-support/pom.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-test-support</artifactId>
|
||||
<name>Spring Cloud Stream Test Support</name>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binder-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2015 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.stream.test.binder;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
|
||||
/**
|
||||
* Maintains a map between (output) channels and messages received (in FIFO order). To be injected in tests that
|
||||
* can then run assertions on the enqueued messages.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
public interface MessageCollector {
|
||||
|
||||
/**
|
||||
* Obtain a queue that will receive messages sent to the given channel.
|
||||
*/
|
||||
public BlockingQueue<Message<?>> forChannel(MessageChannel channel);
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright 2015 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.stream.test.binder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
|
||||
import org.springframework.cloud.stream.binder.Binder;
|
||||
import org.springframework.cloud.stream.test.matcher.MessageQueueMatcher;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.messaging.SubscribableChannel;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A minimal binder that<ul>
|
||||
* <li>does nothing about binding consumers, leaving the channel as-is, so that a test author can interact with it directly,</li>
|
||||
* <li>registers a queue channel on the producer side, so that it is easy to assert what is received.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Eric Bottard
|
||||
* @see MessageQueueMatcher
|
||||
*/
|
||||
public class TestSupportBinder implements Binder<MessageChannel> {
|
||||
|
||||
private final MessageCollectorImpl messageCollector = new MessageCollectorImpl();
|
||||
|
||||
|
||||
@Override
|
||||
public void bindConsumer(String name, MessageChannel inboundBindTarget, Properties properties) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindPubSubConsumer(String name, MessageChannel inboundBindTarget, Properties properties) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a single subscriber to the channel, that enqueues messages for later retrieval and assertion in tests.
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void bindProducer(String name, MessageChannel outboundBindTarget, Properties properties) {
|
||||
final BlockingQueue queue = messageCollector.register(outboundBindTarget);
|
||||
((SubscribableChannel)outboundBindTarget).subscribe(new MessageHandler() {
|
||||
@Override
|
||||
public void handleMessage(Message<?> message) throws MessagingException {
|
||||
queue.add(message);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbindProducer(String name, MessageChannel channel) {
|
||||
messageCollector.unregister(channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindPubSubProducer(String name, MessageChannel outboundBindTarget, Properties properties) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbindConsumers(String name) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbindProducers(String name) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbindConsumer(String name, MessageChannel inboundBindTarget) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindRequestor(String name, MessageChannel requests, MessageChannel replies, Properties properties) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindReplier(String name, MessageChannel requests, MessageChannel replies, Properties properties) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageChannel bindDynamicProducer(String name, Properties properties) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageChannel bindDynamicPubSubProducer(String name, Properties properties) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCapable(Capability capability) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public MessageCollector messageCollector() {
|
||||
return messageCollector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maintains mappings between channels and queues.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
private static class MessageCollectorImpl implements MessageCollector{
|
||||
|
||||
private Map<MessageChannel, BlockingQueue<Message<?>>> results = new HashMap<>();
|
||||
|
||||
private BlockingQueue register(MessageChannel channel) {
|
||||
LinkedBlockingDeque<Message<?>> result = new LinkedBlockingDeque<>();
|
||||
Assert.isTrue(!results.containsKey(channel), "Channel [" + channel + "] was already bound");
|
||||
results.put(channel, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void unregister(MessageChannel channel) {
|
||||
Assert.notNull(results.remove(channel), "Trying to unregister a mapping for an unknown channel [" + channel + "]");
|
||||
}
|
||||
|
||||
public BlockingQueue<Message<?>> forChannel(MessageChannel channel) {
|
||||
BlockingQueue<Message<?>> queue = results.get(channel);
|
||||
Assert.notNull(queue, "Channel [" + channel + "] was not bound by " + TestSupportBinder.class);
|
||||
return queue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2015 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.stream.test.binder;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||
import org.springframework.cloud.stream.binder.Binder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* Installs the {@link TestSupportBinder} and exposes {@link TestSupportBinder.MessageCollectorImpl} to be injected in tests.
|
||||
*
|
||||
* Note that this auto-configuration has higher priority than regular binders, so adding
|
||||
* this on the classpath in test scope is sufficient to have support kick in.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class TestSupportBinderAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public MessageCollector messageCollector() {
|
||||
return testSupportBinder().messageCollector();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestSupportBinder testSupportBinder() {
|
||||
return new TestSupportBinder();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright 2015 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.stream.test.matcher;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.SelfDescribing;
|
||||
|
||||
import org.springframework.cloud.stream.test.binder.TestSupportBinder;
|
||||
import org.springframework.integration.util.Function;
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
/**
|
||||
* A Hamcrest Matcher meant to be used in conjunction with {@link TestSupportBinder}.
|
||||
*
|
||||
* <p>Expected usage is of the form (with appropriate static imports):
|
||||
* <pre>
|
||||
* public class TransformProcessorApplicationTests {
|
||||
*
|
||||
* {@literal @}Autowired
|
||||
* {@literal @}ModuleChannels(TransformProcessor.class)
|
||||
* private Processor processor;
|
||||
*
|
||||
* {@literal @}Autowired
|
||||
* private MessageCollectorImpl messageCollector;
|
||||
*
|
||||
*
|
||||
* {@literal @}Test
|
||||
* public void testUsingExpression() {
|
||||
* processor.input().send(new GenericMessage{@literal <}Object>("hello"));
|
||||
* assertThat(messageCollector.forChannel(processor.output()), receivesPayloadThat(is("hellofoo")).within(10));
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
* </p>
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
public class MessageQueueMatcher<T> extends BaseMatcher<BlockingQueue<Message<?>>> {
|
||||
|
||||
private final Matcher<T> delegate;
|
||||
|
||||
private final long timeout;
|
||||
|
||||
private Extractor<Message<?>, T> extractor;
|
||||
|
||||
private Map<BlockingQueue<Message<?>>, T> actuallyReceived = new HashMap<>();
|
||||
|
||||
private final TimeUnit unit;
|
||||
|
||||
public MessageQueueMatcher(Matcher<T> delegate, long timeout, TimeUnit unit, Extractor<Message<?>, T> extractor) {
|
||||
this.delegate = delegate;
|
||||
this.timeout = timeout;
|
||||
this.unit = unit;
|
||||
this.extractor = extractor;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean matches(Object item) {
|
||||
@SuppressWarnings("unchecked")
|
||||
BlockingQueue<Message<?>> queue = (BlockingQueue<Message<?>>) item;
|
||||
Message<?> received = null;
|
||||
try {
|
||||
if (timeout > 0) {
|
||||
received = queue.poll(timeout, unit);
|
||||
} else if (timeout == 0) {
|
||||
received = queue.poll();
|
||||
} else {
|
||||
received = queue.take();
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
return false;
|
||||
}
|
||||
T unwrapped = extractor.apply(received);
|
||||
actuallyReceived.put(queue, unwrapped);
|
||||
return delegate.matches(unwrapped);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeMismatch(Object item, Description description) {
|
||||
@SuppressWarnings("unchecked")
|
||||
BlockingQueue<Message<?>> queue = (BlockingQueue<Message<?>>) item;
|
||||
T value = actuallyReceived.get(queue);
|
||||
if (value != null) {
|
||||
description.appendText("received: ").appendValue(value);
|
||||
} else {
|
||||
description.appendText("timed out after " + timeout + " " + unit.name().toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
public MessageQueueMatcher<T> within(long timeout, TimeUnit unit) {
|
||||
return new MessageQueueMatcher<>(this.delegate, timeout, unit, this.extractor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("Channel to receive ").appendDescriptionOf(extractor).appendDescriptionOf(delegate);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <P> MessageQueueMatcher<P> receivesMessageThat(Matcher<Message<P>> messageMatcher) {
|
||||
return new MessageQueueMatcher(messageMatcher, -1, null, new Extractor<Message<P>, Message<P>>("a message that ") {
|
||||
@Override
|
||||
public Message<P> apply(Message<P> m) {
|
||||
return m;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <P> MessageQueueMatcher<P> receivesPayloadThat(Matcher<P> payloadMatcher) {
|
||||
return new MessageQueueMatcher(payloadMatcher, -1, null, new Extractor<Message<P>, P>("a message whose payload ") {
|
||||
@Override
|
||||
public P apply(Message<P> m) {
|
||||
return m.getPayload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A transformation to be applied to a received message before asserting, <i>e.g.</i> to only inspect the payload.
|
||||
*/
|
||||
public static abstract class Extractor<R, T> implements Function<R, T>, SelfDescribing {
|
||||
|
||||
private final String behaviorDescription;
|
||||
|
||||
protected Extractor(String behaviorDescription) {
|
||||
this.behaviorDescription = behaviorDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText(behaviorDescription);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration:\
|
||||
org.springframework.cloud.stream.test.binder.TestSupportBinderAutoConfiguration
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2015 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.stream.test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.IntegrationTest;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.cloud.stream.annotation.EnableModule;
|
||||
import org.springframework.cloud.stream.annotation.ModuleChannels;
|
||||
import org.springframework.cloud.stream.annotation.Processor;
|
||||
import org.springframework.cloud.stream.test.binder.MessageCollector;
|
||||
import org.springframework.cloud.stream.test.binder.TestSupportBinder;
|
||||
import org.springframework.integration.annotation.Transformer;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Integration test that validates that {@link org.springframework.cloud.stream.test.binder.TestSupportBinder} applies
|
||||
* correctly.
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = ExampleTest.MyProcessor.class)
|
||||
@IntegrationTest({"server.port=-1"})
|
||||
@DirtiesContext
|
||||
public class ExampleTest {
|
||||
|
||||
@Autowired
|
||||
@ModuleChannels(MyProcessor.class)
|
||||
private Processor processor;
|
||||
|
||||
@Autowired
|
||||
private MessageCollector messageCollector;
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testWiring() {
|
||||
Message<String> message = new GenericMessage<>("hello");
|
||||
processor.input().send(message);
|
||||
Message<String> received = (Message<String>) messageCollector.forChannel(processor.output()).poll();
|
||||
assertThat(received.getPayload(), equalTo("hello world"));
|
||||
}
|
||||
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableModule(Processor.class)
|
||||
public static class MyProcessor {
|
||||
|
||||
@Autowired
|
||||
private Processor channels;
|
||||
|
||||
@Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)
|
||||
public String transform(String in) {
|
||||
return in + " world";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2015 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
|
||||
*
|
||||
* http://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 org.springframework.cloud.stream.test.matcher;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.hamcrest.StringDescription;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
|
||||
/**
|
||||
* Tests for MessageQueueMatcher.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
public class MessageQueueMatcherTest {
|
||||
|
||||
private final BlockingDeque<Message<?>> queue = new LinkedBlockingDeque<>();
|
||||
|
||||
private final StringDescription description = new StringDescription();
|
||||
|
||||
@Test
|
||||
public void testTimeout() {
|
||||
Message<?> msg = new GenericMessage<>("hello");
|
||||
MessageQueueMatcher<?> matcher = MessageQueueMatcher.receivesMessageThat(is(msg)).within(2, TimeUnit.MILLISECONDS);
|
||||
|
||||
boolean result = matcher.matches(queue);
|
||||
assertThat(result, is(false));
|
||||
matcher.describeMismatch(queue, description);
|
||||
assertThat(description.toString(), is("timed out after 2 milliseconds"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatch() {
|
||||
Message<?> msg = new GenericMessage<>("hello");
|
||||
MessageQueueMatcher<?> matcher = MessageQueueMatcher.receivesMessageThat(is(msg));
|
||||
|
||||
queue.offer(msg);
|
||||
|
||||
boolean result = matcher.matches(queue);
|
||||
assertThat(result, is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMisMatch() {
|
||||
Message<?> msg = new GenericMessage<>("hello");
|
||||
Message<?> other = new GenericMessage<>("world");
|
||||
|
||||
MessageQueueMatcher<?> matcher = MessageQueueMatcher.receivesMessageThat(is(msg));
|
||||
|
||||
queue.offer(other);
|
||||
|
||||
boolean result = matcher.matches(queue);
|
||||
assertThat(result, is(false));
|
||||
matcher.describeMismatch(queue, description);
|
||||
assertThat(description.toString(), is("received: <" + other + ">"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtractor() {
|
||||
Message<?> msg = new GenericMessage<>("hello", Collections.singletonMap("foo", (Object) "bar"));
|
||||
|
||||
MessageQueueMatcher.Extractor<Message<?>, String> headerExtractor = new MessageQueueMatcher.Extractor<Message<?>, String>("whose 'foo' header") {
|
||||
@Override
|
||||
public String apply(Message<?> message) {
|
||||
return message.getHeaders().get("foo", String.class);
|
||||
}
|
||||
};
|
||||
|
||||
MessageQueueMatcher<?> matcher = new MessageQueueMatcher<>(is("bar"), -1, null, headerExtractor);
|
||||
queue.offer(msg);
|
||||
boolean result = matcher.matches(queue);
|
||||
assertThat(result, is(true));
|
||||
|
||||
matcher = new MessageQueueMatcher<>(is("wizz"), -1, null, headerExtractor);
|
||||
queue.offer(msg);
|
||||
result = matcher.matches(queue);
|
||||
assertThat(result, is(false));
|
||||
matcher.describeMismatch(queue, description);
|
||||
assertThat(description.toString(), is("received: \"bar\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDescription() {
|
||||
Message<?> msg = new GenericMessage<>("hello");
|
||||
|
||||
MessageQueueMatcher<?> matcher = MessageQueueMatcher.receivesMessageThat(is(msg));
|
||||
|
||||
description.appendDescriptionOf(matcher);
|
||||
assertThat(description.toString(), is("Channel to receive a message that is <" + msg + ">"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user