From 86216fb4e9d17615c748e8a6e57fe70a674674e0 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Mon, 9 Oct 2023 15:37:42 -0500 Subject: [PATCH] Search implemented interfaces for @ServiceConnection fields Fixes gh-37671 --- ...iceConnectionContextCustomizerFactory.java | 4 ++ ...nnectionContextCustomizerFactoryTests.java | 49 ++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ServiceConnectionContextCustomizerFactory.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ServiceConnectionContextCustomizerFactory.java index a22c84dfb8..9c991328b4 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ServiceConnectionContextCustomizerFactory.java +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ServiceConnectionContextCustomizerFactory.java @@ -41,6 +41,7 @@ import org.springframework.util.ReflectionUtils; * @author Moritz Halbritter * @author Andy Wilkinson * @author Phillip Webb + * @author Scott Frederick */ class ServiceConnectionContextCustomizerFactory implements ContextCustomizerFactory { @@ -61,6 +62,9 @@ class ServiceConnectionContextCustomizerFactory implements ContextCustomizerFact if (TestContextAnnotationUtils.searchEnclosingClass(clazz)) { findSources(clazz.getEnclosingClass(), sources); } + for (Class implementedInterface : clazz.getInterfaces()) { + findSources(implementedInterface, sources); + } } @SuppressWarnings("unchecked") diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/ServiceConnectionContextCustomizerFactoryTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/ServiceConnectionContextCustomizerFactoryTests.java index dd7b0a681f..dc487d12c7 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/ServiceConnectionContextCustomizerFactoryTests.java +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/ServiceConnectionContextCustomizerFactoryTests.java @@ -71,7 +71,31 @@ class ServiceConnectionContextCustomizerFactoryTests { } @Test - void createContextCustomizerWhenClassHasNonStaticServiceConnectionFailsWithHepfulException() { + void createContextCustomizerWhenInterfaceHasServiceConnectionsReturnsCustomizer() { + ServiceConnectionContextCustomizer customizer = (ServiceConnectionContextCustomizer) this.factory + .createContextCustomizer(ServiceConnectionsInterface.class, null); + assertThat(customizer).isNotNull(); + assertThat(customizer.getSources()).hasSize(2); + } + + @Test + void createContextCustomizerWhenSuperclassHasServiceConnectionsReturnsCustomizer() { + ServiceConnectionContextCustomizer customizer = (ServiceConnectionContextCustomizer) this.factory + .createContextCustomizer(ServiceConnectionsSubclass.class, null); + assertThat(customizer).isNotNull(); + assertThat(customizer.getSources()).hasSize(2); + } + + @Test + void createContextCustomizerWhenImplementedInterfaceHasServiceConnectionsReturnsCustomizer() { + ServiceConnectionContextCustomizer customizer = (ServiceConnectionContextCustomizer) this.factory + .createContextCustomizer(ServiceConnectionsImpl.class, null); + assertThat(customizer).isNotNull(); + assertThat(customizer.getSources()).hasSize(2); + } + + @Test + void createContextCustomizerWhenClassHasNonStaticServiceConnectionFailsWithHelpfulException() { assertThatIllegalStateException() .isThrownBy(() -> this.factory.createContextCustomizer(NonStaticServiceConnection.class, null)) .withMessage("@ServiceConnection field 'service' must be static"); @@ -79,7 +103,7 @@ class ServiceConnectionContextCustomizerFactoryTests { } @Test - void createContextCustomizerWhenClassHasAnnotationOnNonConnectionFieldFailsWithHepfulException() { + void createContextCustomizerWhenClassHasAnnotationOnNonConnectionFieldFailsWithHelpfulException() { assertThatIllegalStateException() .isThrownBy(() -> this.factory.createContextCustomizer(ServiceConnectionOnWrongFieldType.class, null)) .withMessage("Field 'service2' in " + ServiceConnectionOnWrongFieldType.class.getName() @@ -141,6 +165,27 @@ class ServiceConnectionContextCustomizerFactoryTests { } + interface ServiceConnectionsInterface { + + @ServiceConnection + Container service1 = new MockContainer(); + + @ServiceConnection + Container service2 = new MockContainer(); + + default void dummy() { + } + + } + + static class ServiceConnectionsSubclass extends ServiceConnections { + + } + + static class ServiceConnectionsImpl implements ServiceConnectionsInterface { + + } + static class NonStaticServiceConnection { @ServiceConnection