diff --git a/spring-modulith-test/src/main/java/org/springframework/modulith/test/ModuleTestAutoConfiguration.java b/spring-modulith-test/src/main/java/org/springframework/modulith/test/ModuleTestAutoConfiguration.java index 9ecceec9..237b4917 100644 --- a/spring-modulith-test/src/main/java/org/springframework/modulith/test/ModuleTestAutoConfiguration.java +++ b/spring-modulith-test/src/main/java/org/springframework/modulith/test/ModuleTestAutoConfiguration.java @@ -15,15 +15,13 @@ */ package org.springframework.modulith.test; +import java.util.ArrayList; import java.util.Arrays; -import java.util.HashSet; import java.util.List; -import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.context.annotation.Configuration; @@ -31,7 +29,6 @@ import org.springframework.context.annotation.Import; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.Ordered; import org.springframework.core.type.AnnotationMetadata; -import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; /** @@ -66,49 +63,25 @@ class ModuleTestAutoConfiguration { LOGGER.info("Re-configuring auto-configuration and entity scan packages to: {}.", StringUtils.collectionToDelimitedString(basePackages, ", ")); - setBasePackagesOn(registry, AUTOCONFIG_PACKAGES, "BasePackagesBeanDefinition", "basePackages", basePackages); - setBasePackagesOn(registry, ENTITY_SCAN_PACKAGE, "EntityScanPackagesBeanDefinition", "packageNames", - basePackages); + setBasePackagesOn(registry, AUTOCONFIG_PACKAGES, basePackages); + setBasePackagesOn(registry, ENTITY_SCAN_PACKAGE, basePackages); } - @SuppressWarnings("unchecked") - private void setBasePackagesOn(BeanDefinitionRegistry registry, String beanName, String definitionType, - String fieldName, List packages) { + private void setBasePackagesOn(BeanDefinitionRegistry registry, String beanName, List packages) { if (!registry.containsBeanDefinition(beanName)) { return; } + var packagesToSet = new ArrayList<>(packages); var definition = registry.getBeanDefinition(beanName); + var holder = definition.getConstructorArgumentValues().getArgumentValue(0, String[].class); - // For Boot 2.4, we deal with a BasePackagesBeanDefinition - var field = Arrays.stream(definition.getClass().getDeclaredFields()) - .filter(__ -> definition.getClass().getSimpleName().equals(definitionType)) - .filter(it -> it.getName().equals(fieldName)) - .findFirst() - .orElse(null); + Arrays.stream((String[]) holder.getValue()) + .filter(it -> it.startsWith("org.springframework.modulith")) + .forEach(packagesToSet::add); - if (field != null) { - - // Keep all auto-configuration packages from Moduliths - - ReflectionUtils.makeAccessible(field); - ((Set) ReflectionUtils.getField(field, definition)).stream() - .filter(it -> it.startsWith("org.springframework.modulith")) - .forEach(packages::add); - - ReflectionUtils.setField(field, definition, new HashSet<>(packages)); - - } else { - - ValueHolder holder = definition.getConstructorArgumentValues().getArgumentValue(0, String[].class); - Arrays.stream((String[]) holder.getValue()) - .filter(it -> it.startsWith("org.springframework.modulith")) - .forEach(packages::add); - - // Fall back to customize the bean definition in a Boot 2.3 arrangement - definition.getConstructorArgumentValues().addIndexedArgumentValue(0, packages.toArray(String[]::new)); - } + definition.getConstructorArgumentValues().addIndexedArgumentValue(0, packagesToSet.toArray(String[]::new)); } } } diff --git a/spring-modulith-test/src/test/java/org/springframework/modulith/test/ModuleTestAutoConfigurationIntegrationTests.java b/spring-modulith-test/src/test/java/org/springframework/modulith/test/ModuleTestAutoConfigurationIntegrationTests.java new file mode 100644 index 00000000..449a68f1 --- /dev/null +++ b/spring-modulith-test/src/test/java/org/springframework/modulith/test/ModuleTestAutoConfigurationIntegrationTests.java @@ -0,0 +1,44 @@ +package org.springframework.modulith.test; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.autoconfigure.domain.EntityScanPackages; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; + +/** + * Integration tests for {@link ModuleTestAutoConfiguration}. + * + * @author Oliver Drotbohm + */ +class ModuleTestAutoConfigurationIntegrationTests { + + @Test // GH-360 + void bootstrapsTestWithManualEntityScanOfModulithPackage() { + + var execution = mock(ModuleTestExecution.class); + + doReturn(Stream.of("org.springframework.modulith.test")) + .when(execution).getBasePackages(); + + new ApplicationContextRunner() + .withBean(ModuleTestExecution.class, () -> execution) + .withConfiguration(AutoConfigurations.of(ModuleTestAutoConfiguration.class)) + .withUserConfiguration(ManualModulithEntityScan.class) + .run(ctx -> { + + assertThat(ctx).hasNotFailed(); + assertThat(ctx.getBean(EntityScanPackages.class).getPackageNames()) + .containsExactlyInAnyOrder("org.springframework.modulith.test", + "org.springframework.modulith.events.jpa"); + }); + } + + @EntityScan("org.springframework.modulith.events.jpa") + static class ManualModulithEntityScan {} +}