From c857339e46e913dab3556a7c7c311541fb633108 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Wed, 16 Mar 2022 10:30:10 +0100 Subject: [PATCH] GH-2304 Remove old test support binder Resolves #2304 --- core/pom.xml | 1 - core/spring-cloud-stream-test-support/.jdk8 | 0 core/spring-cloud-stream-test-support/pom.xml | 37 --- .../stream/test/binder/MessageCollector.java | 39 --- .../MessageCollectorAutoConfiguration.java | 39 --- .../TestBinderEnvironmentPostProcessor.java | 44 --- .../stream/test/binder/TestSupportBinder.java | 268 ------------------ .../TestSupportBinderAutoConfiguration.java | 61 ---- .../TestSupportBinderConfiguration.java | 46 --- .../test/matcher/MessageQueueMatcher.java | 164 ----------- .../main/resources/META-INF/spring.binders | 2 - .../main/resources/META-INF/spring.factories | 5 - .../test/matcher/MessageQueueMatcherTest.java | 113 -------- 13 files changed, 819 deletions(-) delete mode 100644 core/spring-cloud-stream-test-support/.jdk8 delete mode 100644 core/spring-cloud-stream-test-support/pom.xml delete mode 100644 core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/MessageCollector.java delete mode 100644 core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/MessageCollectorAutoConfiguration.java delete mode 100644 core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestBinderEnvironmentPostProcessor.java delete mode 100644 core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestSupportBinder.java delete mode 100644 core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestSupportBinderAutoConfiguration.java delete mode 100644 core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestSupportBinderConfiguration.java delete mode 100644 core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/matcher/MessageQueueMatcher.java delete mode 100644 core/spring-cloud-stream-test-support/src/main/resources/META-INF/spring.binders delete mode 100644 core/spring-cloud-stream-test-support/src/main/resources/META-INF/spring.factories delete mode 100644 core/spring-cloud-stream-test-support/src/test/java/org/springframework/cloud/stream/test/matcher/MessageQueueMatcherTest.java diff --git a/core/pom.xml b/core/pom.xml index 84d99726e..e85dd7e22 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -17,7 +17,6 @@ spring-cloud-stream spring-cloud-stream-binder-test - spring-cloud-stream-test-support spring-cloud-stream-test-support-internal spring-cloud-stream-integration-tests docs diff --git a/core/spring-cloud-stream-test-support/.jdk8 b/core/spring-cloud-stream-test-support/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/core/spring-cloud-stream-test-support/pom.xml b/core/spring-cloud-stream-test-support/pom.xml deleted file mode 100644 index 939bb0e73..000000000 --- a/core/spring-cloud-stream-test-support/pom.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - 4.0.0 - - org.springframework.cloud - spring-cloud-stream-parent - 4.0.0-SNAPSHOT - - spring-cloud-stream-test-support - A set of classes to ease testing of Spring Cloud Stream modules. - - - - org.springframework.boot - spring-boot-configuration-processor - true - - - org.springframework.boot - spring-boot-starter-test - - - org.springframework.cloud - spring-cloud-stream - - - org.springframework.boot - spring-boot-autoconfigure - - - com.fasterxml.jackson.core - jackson-databind - - - diff --git a/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/MessageCollector.java b/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/MessageCollector.java deleted file mode 100644 index 47233e5f5..000000000 --- a/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/MessageCollector.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2015-2019 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 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. - * @param channel message channel - * @return blocking queue for stored message - */ - BlockingQueue> forChannel(MessageChannel channel); - -} diff --git a/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/MessageCollectorAutoConfiguration.java b/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/MessageCollectorAutoConfiguration.java deleted file mode 100644 index 0b4b9ec5b..000000000 --- a/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/MessageCollectorAutoConfiguration.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2017-2019 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 org.springframework.cloud.stream.test.binder; - -import org.springframework.cloud.stream.binder.BinderFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.MessageChannel; - -/** - * Automatically registers the {@link MessageCollector} associated with the test binder as - * a bean. - * - * @author Marius Bogoevici - */ -@Configuration -public class MessageCollectorAutoConfiguration { - - @Bean - public MessageCollector messageCollector(BinderFactory binderFactory) { - return ((TestSupportBinder) binderFactory.getBinder("test", MessageChannel.class)) - .messageCollector(); - } - -} diff --git a/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestBinderEnvironmentPostProcessor.java b/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestBinderEnvironmentPostProcessor.java deleted file mode 100644 index 567a54b0e..000000000 --- a/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestBinderEnvironmentPostProcessor.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2017-2019 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 org.springframework.cloud.stream.test.binder; - -import java.util.HashMap; -import java.util.Map; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.env.EnvironmentPostProcessor; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.MapPropertySource; - -/** - * An {@link EnvironmentPostProcessor} that sets some configuration properties for - * {@link TestSupportBinder}. - * - * @author Ilayaperumal Gopinathan - */ -public class TestBinderEnvironmentPostProcessor implements EnvironmentPostProcessor { - - @Override - public void postProcessEnvironment(ConfigurableEnvironment environment, - SpringApplication application) { - Map propertiesToAdd = new HashMap<>(); - propertiesToAdd.put("spring.cloud.stream.binders.test.defaultCandidate", "false"); - environment.getPropertySources() - .addLast(new MapPropertySource("testBinderConfig", propertiesToAdd)); - } - -} diff --git a/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestSupportBinder.java b/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestSupportBinder.java deleted file mode 100644 index a251a9d40..000000000 --- a/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestSupportBinder.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright 2015-2017 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 org.springframework.cloud.stream.test.binder; - -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.LinkedBlockingDeque; - -import org.springframework.cloud.stream.binder.Binder; -import org.springframework.cloud.stream.binder.Binding; -import org.springframework.cloud.stream.binder.ConsumerProperties; -import org.springframework.cloud.stream.binder.ProducerProperties; -import org.springframework.cloud.stream.converter.CompositeMessageConverterFactory; -import org.springframework.cloud.stream.converter.MessageConverterUtils; -import org.springframework.cloud.stream.test.matcher.MessageQueueMatcher; -import org.springframework.integration.channel.AbstractMessageChannel; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.MessageHandler; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.MessagingException; -import org.springframework.messaging.SubscribableChannel; -import org.springframework.messaging.converter.DefaultContentTypeResolver; -import org.springframework.messaging.converter.MessageConverter; -import org.springframework.messaging.support.ChannelInterceptor; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.Assert; -import org.springframework.util.MimeType; -import org.springframework.util.MimeTypeUtils; -import org.springframework.util.StringUtils; - -/** - * A minimal binder that - *
    - *
  • does nothing about binding consumers, leaving the channel as-is, so that a test - * author can interact with it directly,
  • - *
  • registers a queue channel on the producer side, so that it is easy to assert what - * is received.
  • - *
- * - * @author Eric Bottard - * @author Gary Russell - * @author Mark Fisher - * @author Oleg Zhurakousky - * @author Soby Chacko - * @see MessageQueueMatcher - */ -public class TestSupportBinder - implements Binder { - - private final MessageCollectorImpl messageCollector = new MessageCollectorImpl(); - - private final ConcurrentMap messageChannels = new ConcurrentHashMap<>(); - - @Override - public Binding bindConsumer(String name, String group, - MessageChannel inboundBindTarget, ConsumerProperties properties) { - return new TestBinding(inboundBindTarget, null); - } - - /** - * Registers a single subscriber to the channel, that enqueues messages for later - * retrieval and assertion in tests. - */ - @Override - public Binding bindProducer(String name, - MessageChannel outboundBindTarget, ProducerProperties properties) { - final BlockingQueue> queue = this.messageCollector - .register(outboundBindTarget, properties.isUseNativeEncoding()); - ((SubscribableChannel) outboundBindTarget).subscribe(new MessageHandler() { - @Override - public void handleMessage(Message message) throws MessagingException { - queue.add(message); - } - }); - this.messageChannels.put(name, outboundBindTarget); - return new TestBinding(outboundBindTarget, this.messageCollector); - } - - public MessageCollector messageCollector() { - return this.messageCollector; - } - - public MessageChannel getChannelForName(String name) { - return this.messageChannels.get(name); - } - - /** - * Maintains mappings between channels and queues. - * - * @author Eric Bottard - */ - private static class MessageCollectorImpl implements MessageCollector { - - private final Map>> results = new HashMap<>(); - - private BlockingQueue> register(MessageChannel channel, - boolean useNativeEncoding) { - // we need to add this interceptor to ensure MessageCollector's compatibility - // with - // previous versions of SCSt when native encoding is disabled. - if (!useNativeEncoding) { - ((AbstractMessageChannel) channel) - .addInterceptor(new InboundMessageConvertingInterceptor()); - } - LinkedBlockingDeque> result = new LinkedBlockingDeque<>(); - Assert.isTrue(!this.results.containsKey(channel), - "Channel [" + channel + "] was already bound"); - this.results.put(channel, result); - return result; - } - - private void unregister(MessageChannel channel) { - Assert.notNull(this.results.remove(channel), - "Trying to unregister a mapping for an unknown channel [" + channel - + "]"); - } - - @Override - public BlockingQueue> forChannel(MessageChannel channel) { - BlockingQueue> queue = this.results.get(channel); - Assert.notNull(queue, "Channel [" + channel + "] was not bound by " - + TestSupportBinder.class); - return queue; - } - - } - - /** - * @author Marius Bogoevici - */ - private static final class TestBinding implements Binding { - - private final MessageChannel target; - - private final MessageCollectorImpl messageCollector; - - private TestBinding(MessageChannel target, - MessageCollectorImpl messageCollector) { - this.target = target; - this.messageCollector = messageCollector; - } - - @Override - public void unbind() { - if (this.messageCollector != null) { - this.messageCollector.unregister(this.target); - } - } - - } - - /** - * This is really an interceptor to maintain MessageCollector's backward compatibility - * with the behavior established in 1.3 - BINDER_ORIGINAL_CONTENT_TYPE - Kryo and Java - * deserialization - byte[] to String conversion - etc. - */ - private final static class InboundMessageConvertingInterceptor - implements ChannelInterceptor { - - private final DefaultContentTypeResolver contentTypeResolver = new DefaultContentTypeResolver(); - - private final CompositeMessageConverterFactory converterFactory = new CompositeMessageConverterFactory(); - - /* - * Candidate to go into some utils class - */ - private static boolean equalTypeAndSubType(MimeType m1, MimeType m2) { - return m1 != null && m2 != null && m1.getType().equalsIgnoreCase(m2.getType()) - && m1.getSubtype().equalsIgnoreCase(m2.getSubtype()); - } - - @Override - public Message preSend(Message message, MessageChannel channel) { - Class targetClass = null; - MessageConverter converter = null; - MimeType contentType = MimeType.valueOf(this.contentTypeResolver - .resolve(message.getHeaders()).toString()); - - if (contentType != null) { - if (equalTypeAndSubType(MessageConverterUtils.X_JAVA_SERIALIZED_OBJECT, - contentType) - || equalTypeAndSubType(MessageConverterUtils.X_JAVA_OBJECT, - contentType)) { - // for Java and Kryo de-serialization we need to reset the content - // type - message = MessageBuilder.fromMessage(message) - .setHeader(MessageHeaders.CONTENT_TYPE, contentType).build(); - converter = equalTypeAndSubType( - MessageConverterUtils.X_JAVA_SERIALIZED_OBJECT, contentType) - ? this.converterFactory - .getMessageConverterForType(contentType) - : this.converterFactory - .getMessageConverterForAllRegistered(); - String targetClassName = contentType.getParameter("type"); - if (StringUtils.hasText(targetClassName)) { - try { - targetClass = Class.forName(targetClassName, false, - Thread.currentThread().getContextClassLoader()); - } - catch (Exception e) { - throw new IllegalStateException( - "Failed to determine class name for contentType: " - + message.getHeaders(), - e); - } - } - } - - } - - Object payload; - if (converter != null) { - Assert.isTrue( - !(equalTypeAndSubType(MessageConverterUtils.X_JAVA_OBJECT, - contentType) && targetClass == null), - "Cannot deserialize into message since 'contentType` is not " - + "encoded with the actual target type." - + "Consider 'application/x-java-object; type=foo.bar.MyClass'"); - payload = converter.fromMessage(message, targetClass); - } - else { - MimeType deserializeContentType = this.contentTypeResolver - .resolve(message.getHeaders()); - if (deserializeContentType == null) { - deserializeContentType = contentType; - } - payload = deserializeContentType == null ? message.getPayload() : this - .deserializePayload(message.getPayload(), deserializeContentType); - } - message = MessageBuilder.withPayload(payload) - .copyHeaders(message.getHeaders()) - .setHeader(MessageHeaders.CONTENT_TYPE, contentType) - .build(); - return message; - } - - private Object deserializePayload(Object payload, MimeType contentType) { - if (payload instanceof byte[] - && ("text".equalsIgnoreCase(contentType.getType()) - || equalTypeAndSubType(MimeTypeUtils.APPLICATION_JSON, - contentType))) { - payload = new String((byte[]) payload, StandardCharsets.UTF_8); - } - return payload; - } - - } - -} diff --git a/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestSupportBinderAutoConfiguration.java b/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestSupportBinderAutoConfiguration.java deleted file mode 100644 index ead7b84c0..000000000 --- a/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestSupportBinderAutoConfiguration.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2015-2017 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 org.springframework.cloud.stream.test.binder; - -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.AutoConfigureOrder; -import org.springframework.cloud.stream.binder.Binder; -import org.springframework.cloud.stream.binder.BinderFactory; -import org.springframework.cloud.stream.binder.ConsumerProperties; -import org.springframework.cloud.stream.binder.ProducerProperties; -import org.springframework.cloud.stream.config.BindingServiceConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.core.Ordered; -import org.springframework.messaging.MessageChannel; - -/** - * Installs the TestSupportBinder} and exposes - * MessageCollectorImplto be injected in tests. - * - * Note that this auto-configuration has higher priority than regular binder - * configuration, so adding this on the classpath in test scope is sufficient to have - * support kick in and replace all binders with the test binder. - * - * @author Eric Bottard - * @author Marius Bogoevici - */ -@Configuration -@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) -@Import(TestSupportBinderConfiguration.class) -@AutoConfigureBefore(BindingServiceConfiguration.class) -public class TestSupportBinderAutoConfiguration { - - @Bean - @SuppressWarnings("unchecked") - public BinderFactory binderFactory(final Binder binder) { - return new BinderFactory() { - @Override - public Binder getBinder( - String configurationName, Class bindableType) { - return (Binder) binder; - } - }; - } - -} diff --git a/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestSupportBinderConfiguration.java b/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestSupportBinderConfiguration.java deleted file mode 100644 index 775c398b3..000000000 --- a/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestSupportBinderConfiguration.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2017-2019 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 org.springframework.cloud.stream.test.binder; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.cloud.stream.binder.Binder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.MessageChannel; - -/** - * Binder {@link org.springframework.context.annotation.Configuration} for the - * {@link TestSupportBinder} - * - * Either imported by the {@link TestSupportBinderAutoConfiguration} for the test binder - * default usage scenario (superseding all binders on the classpath), or used as a binder - * configuration on the classpath when test binder autoconfiguration is disabled. - * - * @author Marius Bogoevici - */ -@Configuration -@ConditionalOnMissingBean(Binder.class) -public class TestSupportBinderConfiguration { - - private Binder messageChannelBinder = new TestSupportBinder(); - - @Bean - public Binder binder() { - return this.messageChannelBinder; - } - -} diff --git a/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/matcher/MessageQueueMatcher.java b/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/matcher/MessageQueueMatcher.java deleted file mode 100644 index 36b54cc20..000000000 --- a/core/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/matcher/MessageQueueMatcher.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2015-2017 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 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 java.util.function.Function; - -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.messaging.Message; - -/** - * A Hamcrest Matcher meant to be used in conjunction with {@link TestSupportBinder}. - * - * - * @param return type - * @author Eric Bottard - * @author Janne Valkealahti - */ -public class MessageQueueMatcher extends BaseMatcher>> { - - private final Matcher delegate; - - private final long timeout; - - private final TimeUnit unit; - - private Extractor, T> extractor; - - private Map>, T> actuallyReceived = new HashMap<>(); - - public MessageQueueMatcher(Matcher delegate, long timeout, TimeUnit unit, - Extractor, T> extractor) { - this.delegate = delegate; - this.timeout = timeout; - this.unit = (unit != null ? unit : TimeUnit.SECONDS); - this.extractor = extractor; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static

MessageQueueMatcher

receivesMessageThat( - Matcher> messageMatcher) { - return new MessageQueueMatcher(messageMatcher, 5, TimeUnit.SECONDS, - new Extractor, Message

>("a message that ") { - @Override - public Message

apply(Message

m) { - return m; - } - }); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static

MessageQueueMatcher

receivesPayloadThat( - Matcher

payloadMatcher) { - return new MessageQueueMatcher(payloadMatcher, 5, TimeUnit.SECONDS, - new Extractor, P>("a message whose payload ") { - @Override - public P apply(Message

m) { - return m.getPayload(); - } - }); - } - - @Override - public boolean matches(Object item) { - @SuppressWarnings("unchecked") - BlockingQueue> queue = (BlockingQueue>) item; - Message received = null; - try { - if (this.timeout > 0) { - received = queue.poll(this.timeout, this.unit); - } - else if (this.timeout == 0) { - received = queue.poll(); - } - else { - received = queue.take(); - } - } - catch (InterruptedException e) { - return false; - } - T unwrapped = this.extractor.apply(received); - this.actuallyReceived.put(queue, unwrapped); - return this.delegate.matches(unwrapped); - } - - @Override - public void describeMismatch(Object item, Description description) { - @SuppressWarnings("unchecked") - BlockingQueue> queue = (BlockingQueue>) item; - T value = this.actuallyReceived.get(queue); - if (value != null) { - description.appendText("received: ").appendValue(value); - } - else { - description.appendText("timed out after " + this.timeout + " " - + this.unit.name().toLowerCase()); - } - } - - public MessageQueueMatcher within(long timeout, TimeUnit unit) { - return new MessageQueueMatcher<>(this.delegate, timeout, unit, this.extractor); - } - - public MessageQueueMatcher immediately() { - return new MessageQueueMatcher<>(this.delegate, 0, null, this.extractor); - } - - public MessageQueueMatcher indefinitely() { - return new MessageQueueMatcher<>(this.delegate, -1, null, this.extractor); - } - - @Override - public void describeTo(Description description) { - description.appendText("Channel to receive ").appendDescriptionOf(this.extractor) - .appendDescriptionOf(this.delegate); - } - - /** - * A transformation to be applied to a received message before asserting, e.g. - * to only inspect the payload. - * - * @param input type - * @param return type - */ - public static abstract class Extractor - implements Function, SelfDescribing { - - private final String behaviorDescription; - - protected Extractor(String behaviorDescription) { - this.behaviorDescription = behaviorDescription; - } - - @Override - public void describeTo(Description description) { - description.appendText(this.behaviorDescription); - } - - } - -} diff --git a/core/spring-cloud-stream-test-support/src/main/resources/META-INF/spring.binders b/core/spring-cloud-stream-test-support/src/main/resources/META-INF/spring.binders deleted file mode 100644 index f12cc2353..000000000 --- a/core/spring-cloud-stream-test-support/src/main/resources/META-INF/spring.binders +++ /dev/null @@ -1,2 +0,0 @@ -test:\ -org.springframework.cloud.stream.test.binder.TestSupportBinderConfiguration diff --git a/core/spring-cloud-stream-test-support/src/main/resources/META-INF/spring.factories b/core/spring-cloud-stream-test-support/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 1bf7aa99f..000000000 --- a/core/spring-cloud-stream-test-support/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,5 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.springframework.cloud.stream.test.binder.TestSupportBinderAutoConfiguration,\ -org.springframework.cloud.stream.test.binder.MessageCollectorAutoConfiguration -org.springframework.boot.env.EnvironmentPostProcessor=\ - org.springframework.cloud.stream.test.binder.TestBinderEnvironmentPostProcessor diff --git a/core/spring-cloud-stream-test-support/src/test/java/org/springframework/cloud/stream/test/matcher/MessageQueueMatcherTest.java b/core/spring-cloud-stream-test-support/src/test/java/org/springframework/cloud/stream/test/matcher/MessageQueueMatcherTest.java deleted file mode 100644 index 5202f552a..000000000 --- a/core/spring-cloud-stream-test-support/src/test/java/org/springframework/cloud/stream/test/matcher/MessageQueueMatcherTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2015-2019 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 org.springframework.cloud.stream.test.matcher; - -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.jupiter.api.Test; - -import org.springframework.messaging.Message; -import org.springframework.messaging.support.GenericMessage; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.hamcrest.Matchers.is; - -/** - * Tests for MessageQueueMatcher. - * - * @author Eric Bottard - */ -public class MessageQueueMatcherTest { - - private final BlockingDeque> 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(this.queue); - assertThat(result).isFalse(); - matcher.describeMismatch(this.queue, this.description); - assertThat(this.description.toString()) - .isEqualTo("timed out after 2 milliseconds"); - } - - @Test - public void testMatch() { - Message msg = new GenericMessage<>("hello"); - MessageQueueMatcher matcher = MessageQueueMatcher.receivesMessageThat(is(msg)); - this.queue.offer(msg); - boolean result = matcher.matches(this.queue); - assertThat(result).isTrue(); - } - - @Test - public void testMismatch() { - Message msg = new GenericMessage<>("hello"); - Message other = new GenericMessage<>("world"); - MessageQueueMatcher matcher = MessageQueueMatcher.receivesMessageThat(is(msg)); - this.queue.offer(other); - boolean result = matcher.matches(this.queue); - assertThat(result).isFalse(); - matcher.describeMismatch(this.queue, this.description); - assertThat(this.description.toString()).isEqualTo(("received: <" + other + ">")); - } - - @Test - public void testExtractor() { - Message msg = new GenericMessage<>("hello", - Collections.singletonMap("foo", (Object) "bar")); - - MessageQueueMatcher.Extractor, String> headerExtractor; - headerExtractor = new MessageQueueMatcher.Extractor, 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); - this.queue.offer(msg); - boolean result = matcher.matches(this.queue); - assertThat(result); - matcher = new MessageQueueMatcher<>(is("wizz"), -1, null, headerExtractor); - this.queue.offer(msg); - result = matcher.matches(this.queue); - assertThat(result).isFalse(); - matcher.describeMismatch(this.queue, this.description); - assertThat(this.description.toString()).isEqualTo(("received: \"bar\"")); - } - - @Test - public void testDescription() { - Message msg = new GenericMessage<>("hello"); - MessageQueueMatcher matcher = MessageQueueMatcher.receivesMessageThat(is(msg)); - this.description.appendDescriptionOf(matcher); - assertThat(this.description.toString()) - .isEqualTo(("Channel to receive a message that is <" + msg + ">")); - } - -}