From 1f4105591770293340a73e392ef4553eddd95d2b Mon Sep 17 00:00:00 2001 From: kutmk Date: Tue, 14 May 2024 00:29:00 +0900 Subject: [PATCH] Add @EnableTestBinder annotation (#2947) * Add @EnableTestBinder annotation * Use @EnableTestBinder in tests * Update copyright and author tag * Add javadoc * Update explanation to use @EnableTestBinder Resolves https://github.com/spring-cloud/spring-cloud-stream/issues/2931 --- .../binder/tck/ContentTypeTckTests.java | 40 +++++++++--------- .../stream/binding/BindingServiceTests.java | 12 +++--- .../config/BindingHandlerAdviseTests.java | 12 +++--- .../stream/config/RetryTemplateTests.java | 10 ++--- .../stream/binder/test/EnableTestBinder.java | 42 +++++++++++++++++++ .../ROOT/pages/spring-cloud-stream.adoc | 3 +- .../spring_integration_test_binder.adoc | 19 +++------ 7 files changed, 85 insertions(+), 53 deletions(-) create mode 100644 core/spring-cloud-stream-test-binder/src/main/java/org/springframework/cloud/stream/binder/test/EnableTestBinder.java diff --git a/core/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/binder/tck/ContentTypeTckTests.java b/core/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/binder/tck/ContentTypeTckTests.java index b8f07a244..e5fd4a9ab 100644 --- a/core/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/binder/tck/ContentTypeTckTests.java +++ b/core/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/binder/tck/ContentTypeTckTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 the original author or authors. + * Copyright 2017-2024 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. @@ -29,14 +29,13 @@ import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.function.json.JsonMapper; +import org.springframework.cloud.stream.binder.test.EnableTestBinder; import org.springframework.cloud.stream.binder.test.InputDestination; import org.springframework.cloud.stream.binder.test.OutputDestination; import org.springframework.cloud.stream.binder.test.TestChannelBinder; -import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; import org.springframework.lang.Nullable; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHeaders; @@ -58,6 +57,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Oleg Zhurakousky * @author Gary Russell * @author Byungjun You + * @author Kotaro Matsumoto * */ class ContentTypeTckTests { @@ -518,7 +518,7 @@ class ContentTypeTckTests { } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class CollectionWithParameterizedTypes { @@ -531,7 +531,7 @@ class ContentTypeTckTests { } } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class PojoToPojoConfiguration { @@ -541,7 +541,7 @@ class ContentTypeTckTests { } } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class PojoToStringConfiguration { @@ -551,7 +551,7 @@ class ContentTypeTckTests { } } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class PojoToByteArrayConfiguration { @@ -561,7 +561,7 @@ class ContentTypeTckTests { } } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class ByteArrayToPojoConfiguration { @@ -571,7 +571,7 @@ class ContentTypeTckTests { } } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class StringToPojoConfiguration { @@ -581,7 +581,7 @@ class ContentTypeTckTests { } } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class TypelessToPojoConfiguration { @@ -593,7 +593,7 @@ class ContentTypeTckTests { } } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class TypelessMessageToPojoConfiguration { @@ -605,7 +605,7 @@ class ContentTypeTckTests { } } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class TypelessToMessageConfiguration { @@ -616,7 +616,7 @@ class ContentTypeTckTests { } } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class TypelessToMessageTextOnlyContentTypeConfiguration { @@ -630,7 +630,7 @@ class ContentTypeTckTests { } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class ByteArrayToByteArrayConfiguration { @@ -640,7 +640,7 @@ class ContentTypeTckTests { } } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class StringToStringConfiguration { @@ -650,7 +650,7 @@ class ContentTypeTckTests { } } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class StringToMapMessageConfiguration { @@ -663,7 +663,7 @@ class ContentTypeTckTests { } } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class PojoMessageToStringMessageConfiguration { @@ -799,7 +799,7 @@ class ContentTypeTckTests { } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class MapInputConfiguration { @@ -809,7 +809,7 @@ class ContentTypeTckTests { } } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class ListInputConfiguration { @Bean @@ -818,7 +818,7 @@ class ContentTypeTckTests { } } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class MessageHeadersInputConfiguration { diff --git a/core/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/binding/BindingServiceTests.java b/core/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/binding/BindingServiceTests.java index a5dbd709e..c2c54c658 100644 --- a/core/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/binding/BindingServiceTests.java +++ b/core/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/binding/BindingServiceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2023 the original author or authors. + * Copyright 2015-2024 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. @@ -52,7 +52,7 @@ import org.springframework.cloud.stream.binder.ConsumerProperties; import org.springframework.cloud.stream.binder.DefaultBinderFactory; import org.springframework.cloud.stream.binder.DefaultBinderTypeRegistry; import org.springframework.cloud.stream.binder.ProducerProperties; -import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration; +import org.springframework.cloud.stream.binder.test.EnableTestBinder; import org.springframework.cloud.stream.config.BindingProperties; import org.springframework.cloud.stream.config.BindingServiceConfiguration; import org.springframework.cloud.stream.config.BindingServiceProperties; @@ -61,7 +61,6 @@ import org.springframework.cloud.stream.utils.IntegrationTestsMockBinderConfigur import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Import; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.test.util.TestUtils; import org.springframework.messaging.Message; @@ -90,6 +89,7 @@ import static org.mockito.Mockito.when; * @author Michael Michailidis * @author Chris Bono * @author Artem Bilan + * @author Kotaro Matsumoto */ class BindingServiceTests { @@ -591,13 +591,13 @@ class BindingServiceTests { return bindingServiceProperties; } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class DefaultConsumerPropertiesTestSink { } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class FooConfiguration { @@ -608,7 +608,7 @@ class BindingServiceTests { } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class BarConfiguration { diff --git a/core/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/BindingHandlerAdviseTests.java b/core/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/BindingHandlerAdviseTests.java index 6616ab054..4d68796ba 100644 --- a/core/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/BindingHandlerAdviseTests.java +++ b/core/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/BindingHandlerAdviseTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2023 the original author or authors. + * Copyright 2018-2024 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. @@ -29,9 +29,8 @@ import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationPropertiesBindException; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration; +import org.springframework.cloud.stream.binder.test.EnableTestBinder; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Import; import org.springframework.validation.annotation.Validated; import static org.assertj.core.api.Assertions.assertThat; @@ -41,6 +40,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; /** * @author Oleg Zhurakousky * @author Soby Chacko + * @author Kotaro Matsumoto * */ class BindingHandlerAdviseTests { @@ -76,7 +76,7 @@ class BindingHandlerAdviseTests { .run("--spring.jmx.enabled=false")); } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class NonValidatedConfiguration { @@ -105,7 +105,7 @@ class BindingHandlerAdviseTests { } } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class ValidatedConfiguration { @@ -136,7 +136,7 @@ class BindingHandlerAdviseTests { } } -@Import(TestChannelBinderConfiguration.class) +@EnableTestBinder @EnableAutoConfiguration @EnableConfigurationProperties(ValidatedProps.class) class SampleConfiguration { diff --git a/core/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/RetryTemplateTests.java b/core/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/RetryTemplateTests.java index 2b40979da..5563aff65 100644 --- a/core/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/RetryTemplateTests.java +++ b/core/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/RetryTemplateTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2023 the original author or authors. + * Copyright 2018-2024 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. @@ -29,10 +29,9 @@ import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.stream.annotation.StreamRetryTemplate; import org.springframework.cloud.stream.binder.AbstractBinder; import org.springframework.cloud.stream.binder.ConsumerProperties; -import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration; +import org.springframework.cloud.stream.binder.test.EnableTestBinder; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Import; import org.springframework.retry.support.RetryTemplate; import static org.assertj.core.api.Assertions.assertThat; @@ -40,6 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat; /** * @author Oleg Zhurakousky * @author Soby Chacko + * @author Kotaro Matsumoto */ class RetryTemplateTests { @@ -82,7 +82,7 @@ class RetryTemplateTests { assertThat(retryTemplate).isEqualTo(retryTemplateTwo); } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class SpecificCustomRetryTemplateConfiguration { @@ -107,7 +107,7 @@ class RetryTemplateTests { } } - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder @EnableAutoConfiguration public static class SingleCustomRetryTemplateConfiguration { diff --git a/core/spring-cloud-stream-test-binder/src/main/java/org/springframework/cloud/stream/binder/test/EnableTestBinder.java b/core/spring-cloud-stream-test-binder/src/main/java/org/springframework/cloud/stream/binder/test/EnableTestBinder.java new file mode 100644 index 000000000..d3ae2c4d4 --- /dev/null +++ b/core/spring-cloud-stream-test-binder/src/main/java/org/springframework/cloud/stream/binder/test/EnableTestBinder.java @@ -0,0 +1,42 @@ +/* + * Copyright 2024-2024 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.binder.test; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.context.annotation.Import; + +/** + * This annotation enables the Spring Integration Test Binder when applied to a class. + * + * Please see {@link TestChannelBinderConfiguration} and {@link TestChannelBinder} for more details. + * + * @author Kotaro Matsumoto + * @see TestChannelBinderConfiguration + * @see TestChannelBinder + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Import(TestChannelBinderConfiguration.class) +public @interface EnableTestBinder { + +} diff --git a/docs/modules/ROOT/pages/spring-cloud-stream.adoc b/docs/modules/ROOT/pages/spring-cloud-stream.adoc index 11d9de194..abe0f9ddc 100644 --- a/docs/modules/ROOT/pages/spring-cloud-stream.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-stream.adoc @@ -48,7 +48,7 @@ The following listing shows the corresponding test: [source,java] ---- @SpringBootTest(classes = SampleApplication.class) -@Import({TestChannelBinderConfiguration.class}) +@EnableTestBinder class BootTestStreamApplicationTests { @Autowired @@ -70,4 +70,3 @@ class BootTestStreamApplicationTests { Spring Cloud Stream provides a number of abstractions and primitives that simplify the writing of message-driven microservice applications. The rest of this reference manual provides additional details. - diff --git a/docs/modules/ROOT/pages/spring-cloud-stream/spring_integration_test_binder.adoc b/docs/modules/ROOT/pages/spring-cloud-stream/spring_integration_test_binder.adoc index 0e1eb2c18..831e2d96b 100644 --- a/docs/modules/ROOT/pages/spring-cloud-stream/spring_integration_test_binder.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-stream/spring_integration_test_binder.adoc @@ -13,7 +13,7 @@ This test binder acts as a bridge between _unit_ and _integration_ testing and i [[test-binder-configuration]] === Test Binder configuration -To enable Spring Integration test binder, all you need is to add it as a dependency. +To enable Spring Integration test binder, you need to add it as a dependency and annotate your class with `@EnableTestBinder`. ***Add required dependencies*** @@ -38,7 +38,8 @@ testImplementation("org.springframework.cloud:spring-cloud-stream-test-binder") [[test-binder-usage]] === Test Binder usage -Now you can test your microservice as a simple unit test +Now you can test your microservice as a simple unit test. +To enable the Test Binder, annotate your class with `@EnableTestBinder`. [source,java] ---- @@ -58,7 +59,7 @@ public class SampleStreamTests { } @SpringBootApplication - @Import(TestChannelBinderConfiguration.class) + @EnableTestBinder public static class SampleConfiguration { @Bean public Function uppercase() { @@ -201,7 +202,7 @@ public void samplePollingTest() { System.out.println("Message 3: " + new String(destination.receive().getPayload())); } -@Import(TestChannelBinderConfiguration.class) +@EnableTestBinder @EnableAutoConfiguration public static class SamplePolledConfiguration { @Bean @@ -260,13 +261,3 @@ Message 3: MY OWN DATA 20BF2E64-7FF4-4CB6-A823-4053D30B5C74 NOTE: DO NOT name this bean `messageSource` as it is going to be in conflict with the bean of the same name (different type) provided by Spring Boot for unrelated reasons. - -[[special-note-on-mixing-test-binder-and-regular-middleware-binder-for-testing]] -== Special Note on Mixing Test Binder and Regular Middleware Binder for Testing - -The Spring Integration based test binder is provided for testing the application without involving an actual middleware based binder such as the Kafka or RabbitMQ binder. -As described in the sections above, the test binder helps you to verify the application behavior quickly by relying on the in-memory Spring Integration channels. -When the test binder is present on the test classpath, Spring Cloud Stream will try to use this binder for all testing purposes wherever it needs a binder for communication. -In other words, you cannot mix both the test binder and a regular middleware binder for testing purposes in the same module. -After testing the application with the test binder, if you want to continue doing further integration tests using the actual middleware binder, it is recommended to add those tests that use the actual binder in a separate module so that those tests can make the proper connection to the actual middleware rather than relying on the in-memory channels provided by the test binder. -