174 lines
28 KiB
HTML
174 lines
28 KiB
HTML
<html><head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
|
<title>13. Testing</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-stream.html" title="Spring Cloud Stream Reference Guide"><link rel="up" href="multi__preface.html" title="Part I. Preface"><link rel="prev" href="multi__inter_application_communication.html" title="12. Inter-Application Communication"><link rel="next" href="multi__health_indicator.html" title="14. Health Indicator"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">13. Testing</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__inter_application_communication.html">Prev</a> </td><th width="60%" align="center">Part I. Preface</th><td width="20%" align="right"> <a accesskey="n" href="multi__health_indicator.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_testing" href="#_testing"></a>13. Testing</h2></div></div></div><p>Spring Cloud Stream provides support for testing your microservice applications without connecting to a messaging system.
|
|
You can do that by using the <code class="literal">TestSupportBinder</code> provided by the <code class="literal">spring-cloud-stream-test-support</code> library, which can be added as a test dependency to the application, as shown in the following example:</p><pre class="programlisting"> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-stream-test-support<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The <code class="literal">TestSupportBinder</code> uses the Spring Boot autoconfiguration mechanism to supersede the other binders found on the classpath.
|
|
Therefore, when adding a binder as a dependency, you must make sure that the <code class="literal">test</code> scope is being used.</p></td></tr></table></div><p>The <code class="literal">TestSupportBinder</code> lets you interact with the bound channels and inspect any messages sent and received by the application.</p><p>For outbound message channels, the <code class="literal">TestSupportBinder</code> registers a single subscriber and retains the messages emitted by the application in a <code class="literal">MessageCollector</code>.
|
|
They can be retrieved during tests and have assertions made against them.</p><p>You can also send messages to inbound message channels so that the consumer application can consume the messages.
|
|
The following example shows how to test both input and output channels on a processor:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RunWith(SpringRunner.class)</xslthl:annotation>
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> ExampleTest {
|
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> Processor processor;
|
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> MessageCollector messageCollector;
|
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SuppressWarnings("unchecked")</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> testWiring() {
|
|
Message<String> message = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> GenericMessage<>(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"hello"</span>);
|
|
processor.input().send(message);
|
|
Message<String> received = (Message<String>) messageCollector.forChannel(processor.output()).poll();
|
|
assertThat(received.getPayload(), equalTo(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"hello world"</span>));
|
|
}
|
|
|
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootApplication</xslthl:annotation>
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableBinding(Processor.class)</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyProcessor {
|
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> Processor channels;
|
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String transform(String in) {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> in + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">" world"</span>;
|
|
}
|
|
}
|
|
}</pre><p>In the preceding example, we create an application that has an input channel and an output channel, both bound through the <code class="literal">Processor</code> interface.
|
|
The bound interface is injected into the test so that we can have access to both channels.
|
|
We send a message on the input channel, and we use the <code class="literal">MessageCollector</code> provided by Spring Cloud Stream’s test support to capture that the message has been sent to the output channel as a result.
|
|
Once we have received the message, we can validate that the component functions correctly.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_disabling_the_test_binder_autoconfiguration" href="#_disabling_the_test_binder_autoconfiguration"></a>13.1 Disabling the Test Binder Autoconfiguration</h2></div></div></div><p>The intent behind the test binder superseding all the other binders on the classpath is to make it easy to test your applications without making changes to your production dependencies.
|
|
In some cases (for example, integration tests) it is useful to use the actual production binders instead, and that requires disabling the test binder autoconfiguration.
|
|
To do so, you can exclude the <code class="literal">org.springframework.cloud.stream.test.binder.TestSupportBinderAutoConfiguration</code> class by using one of the Spring Boot autoconfiguration exclusion mechanisms, as shown in the following example:</p><pre class="programlisting"> <xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootApplication(exclude = TestSupportBinderAutoConfiguration.class)</xslthl:annotation>
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableBinding(Processor.class)</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyProcessor {
|
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String transform(String in) {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> in + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">" world"</span>;
|
|
}
|
|
}</pre><p>When autoconfiguration is disabled, the test binder is available on the classpath, and its <code class="literal">defaultCandidate</code> property is set to <code class="literal">false</code> so that it does not interfere with the regular user configuration. It can be referenced under the name, <code class="literal">test</code>, as shown in the following example:</p><p><code class="literal">spring.cloud.stream.defaultBinder=test</code></p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring_integration_test_binder" href="#spring_integration_test_binder"></a>13.2 Spring Integration Test Binder</h2></div></div></div><p>Current test binder was specifically designed to facilitate <span class="emphasis"><em>unit testing</em></span> of the actual messaging components and thus bypasses some of the core functionality of the binder API.
|
|
While such light-weight approach is sufficient for a lot of cases, it usually requires additional <span class="emphasis"><em>integration testing</em></span> with real binders (e.g., Rabbit, Kafka etc).</p><p>To begin bridging the gap between <span class="emphasis"><em>unit</em></span> and <span class="emphasis"><em>integration</em></span> testing we’ve developed a new test binder which uses <a class="link" href="https://spring.io/projects/spring-integration" target="_top">Spring Integration</a> framework
|
|
as an in-JVM Message Broker essentially giving you the best of both worlds - a real binder without the networking.</p><p>To enable Spring Integration Test Binder all you need is:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Add required dependencies</li><li class="listitem">Remove the dependency for <code class="literal">spring-cloud-stream-test-support</code></li></ul></div><p><span class="strong"><strong><span class="strong"><strong>Add required dependencies</strong></span></strong></span></p><p>Below is the example of the required Maven POM entries which could be easily retrofitted into Gradle.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-stream<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${spring.cloud.strea.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><type></span>test-jar<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></type></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><classifier></span>test-binder<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></classifier></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
|
. . .
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugins></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugin></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.apache.maven.plugins<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>maven-jar-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><executions></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><execution></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><includes></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><include></span>**/integration/*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></include></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></includes></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><classifier></span>test-binder<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></classifier></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></configuration></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><goals></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><goal></span>test-jar<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></goal></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></goals></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></execution></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></executions></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugin></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugins></span></pre><p><span class="strong"><strong><span class="strong"><strong>Remove the dependency for <code class="literal">spring-cloud-stream-test-support</code></strong></span></strong></span></p><p>To avoid conflicts with the existing test binder you must eremove the following entry</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-stream-test-support<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p>Now you can test your microservice as a simple unit test</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootApplication</xslthl:annotation>
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableBinding(Processor.class)</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> DemoTestBinderApplication {
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> main(String[] args) {
|
|
SpringApplication.run(DemoTestBinderApplication.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>, args);
|
|
}
|
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@StreamListener(Processor.INPUT)</xslthl:annotation>
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SendTo(Processor.OUTPUT)</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String echo(String value) {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> value;
|
|
}
|
|
}
|
|
|
|
. . .
|
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> sampleTest() {
|
|
ApplicationContext context = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> SpringApplicationBuilder(
|
|
TestChannelBinderConfiguration.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>,
|
|
DemoTestBinderApplication.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)
|
|
.web(WebApplicationType.NONE).run();
|
|
InputDestination source = context.getBean(InputDestination.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);
|
|
OutputDestination target = context.getBean(OutputDestination.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);
|
|
source.send(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> GenericMessage<<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">byte</span>[]>(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"hello"</span>.getBytes()));
|
|
System.out.println(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Result: "</span> + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> String(target.receive().getPayload()));
|
|
}</pre><p>In the above you simply create an ApplicationContext with your configuration (your application) while additionally supplying <code class="literal">TestChannelBinderConfiguration</code>
|
|
provided by the framework. Then you access <code class="literal">InputDestination</code> and <code class="literal">OutputDestination</code> beans to send/receive messages. In the context of this binder
|
|
<code class="literal">InputDestination</code> and <code class="literal">OutputDestination</code> emulate remote destinations such as Rabbit <span class="emphasis"><em>exchange/queue</em></span> or Kafka <span class="emphasis"><em>topic</em></span>.</p><p>In the future we plan to simplify the API.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>In its current state Spring Integration Test Binder only supports the three bindings provided by the framework (Source, Processor, Sink) specifically to promote
|
|
light-weight microservices architectures rather then general purpose messaging applications.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_spring_integration_test_binder_and_pollablemessagesource" href="#_spring_integration_test_binder_and_pollablemessagesource"></a>13.2.1 Spring Integration Test Binder and PollableMessageSource</h3></div></div></div><p>Spring Integration Test Binder also allows you to write tests when working with <code class="literal">PollableMessageSource</code> (see <a class="xref" href="multi__programming_model.html#spring-cloud-streams-overview-using-polled-consumers" title="7.3.5 Using Polled Consumers">Section 7.3.5, “Using Polled Consumers”</a> for more details).</p><p>The important thing that needs to be understood though is that polling is not event-driven, and that <code class="literal">PollableMessageSource</code> is a strategy which exposes operation to produce (poll for) a Message (singular).
|
|
How often you poll or how many threads you use or where you’re polling from (message queue or file system) is entirely up to you;
|
|
In other words it is your responsibility to configure Poller or Threads or the actual source of Message. Luckily Spring has plenty of abstractions to configure exactly that.</p><p>Let’s look at the example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Test</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> samplePollingTest() {
|
|
ApplicationContext context = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> SpringApplicationBuilder(SamplePolledConfiguration.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)
|
|
.web(WebApplicationType.NONE)
|
|
.run(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"--spring.jmx.enabled=false"</span>);
|
|
OutputDestination destination = context.getBean(OutputDestination.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);
|
|
System.out.println(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Message 1: "</span> + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> String(destination.receive().getPayload()));
|
|
System.out.println(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Message 2: "</span> + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> String(destination.receive().getPayload()));
|
|
System.out.println(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Message 3: "</span> + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> String(destination.receive().getPayload()));
|
|
}
|
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableBinding(SamplePolledConfiguration.PolledConsumer.class)</xslthl:annotation>
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Import(TestChannelBinderConfiguration.class)</xslthl:annotation>
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableAutoConfiguration</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> SamplePolledConfiguration {
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> ApplicationRunner poller(PollableMessageSource polledMessageSource, MessageChannel output, TaskExecutor taskScheduler) {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> args -> {
|
|
taskScheduler.execute(() -> {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">for</span> (<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> i = <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number>; i < <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number>; i++) {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (!polledMessageSource.poll(m -> {
|
|
String newPayload = ((String) m.getPayload()).toUpperCase();
|
|
output.send(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> GenericMessage<>(newPayload));
|
|
})) {
|
|
Thread.sleep(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2000</xslthl:number>);
|
|
}
|
|
}
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">catch</span> (Exception e) {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// handle failure</span>
|
|
}
|
|
}
|
|
});
|
|
};
|
|
}
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> PolledConsumer <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Source {
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Input</xslthl:annotation>
|
|
PollableMessageSource pollableSource();
|
|
}
|
|
}</pre><p>The above (very rudimentary) example will produce 3 messages in 2 second intervals sending them to the output destination of <code class="literal">Source</code>
|
|
which this binder sends to <code class="literal">OutputDestination</code> where we retrieve them (for any assertions).
|
|
Currently it prints the following:</p><pre class="programlisting">Message 1: POLLED DATA
|
|
Message 2: POLLED DATA
|
|
Message 3: POLLED DATA</pre><p>As you can see the data is the same. That is because this binder defines a default implementation of the actual <code class="literal">MessageSource</code> - the source
|
|
from which the Messages are polled using <code class="literal">poll()</code> operation. While sufficient for most testing scenarios, there are cases where you may want
|
|
to define your own <code class="literal">MessageSource</code>. To do so simply configure a bean of type <code class="literal">MessageSource</code> in your test configuration providing your own
|
|
implementation of Message sourcing.</p><p>Here is the example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> MessageSource<?> source() {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> () -> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> GenericMessage<>(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"My Own Data "</span> + UUID.randomUUID());
|
|
}</pre><p>rendering the following output;</p><pre class="programlisting">Message 1: MY OWN DATA 1C180A91-E79F-494F-ABF4-BA3F993710DA
|
|
Message 2: MY OWN DATA D8F3A477-5547-41B4-9434-E69DA7616FEE
|
|
Message 3: MY OWN DATA 20BF2E64-7FF4-4CB6-A823-4053D30B5C74</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>DO NOT name this bean <code class="literal">messageSource</code> as it is going to be in conflict with the bean of the same name (different type)
|
|
provided by Spring Boot for unrelated reasons.</p></td></tr></table></div></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__inter_application_communication.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__preface.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__health_indicator.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">12. Inter-Application Communication </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-stream.html">Home</a></td><td width="40%" align="right" valign="top"> 14. Health Indicator</td></tr></table></div></body></html> |