From 88f081b1cdd0c19b16c72992d4e74e578759c665 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Sun, 8 Mar 2026 13:33:41 +0100 Subject: [PATCH] Resolve context initializers only once in AbstractTestContextBootstrapper The internal buildMergedContextConfiguration() method in AbstractTestContextBootstrapper originally resolved the ApplicationContextInitializer set only once. However, the changes made in commit 2244461778 introduced a regression resulting in the initializers being resolved twice: once for validation and once for actually building the merged context configuration. In addition, the resolution for validation does not honor the inheritInitializers flag in ContextConfigurationAttributes. To address these issues, buildMergedContextConfiguration() once again resolves the context initializers once via ApplicationContextInitializerUtils.resolveInitializerClasses(). See gh-18528 Closes gh-36430 (cherry picked from commit 463138acbcc7b15eaa2f8f8a0135e5a6584a8648) --- .../context/support/AbstractTestContextBootstrapper.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java b/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java index 2076ce7e2dd..0855da245a5 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java @@ -29,6 +29,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeanInstantiationException; import org.springframework.beans.BeanUtils; +import org.springframework.context.ApplicationContextInitializer; import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.lang.Nullable; import org.springframework.test.context.BootstrapContext; @@ -304,8 +305,6 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot ContextLoader contextLoader = resolveContextLoader(testClass, configAttributesList); List locations = new ArrayList<>(); List> classes = new ArrayList<>(); - List> initializers = new ArrayList<>(); - for (ContextConfigurationAttributes configAttributes : configAttributesList) { if (logger.isTraceEnabled()) { logger.trace(String.format("Processing locations and classes for context configuration attributes %s", @@ -323,12 +322,13 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot locations.addAll(0, Arrays.asList(processedLocations)); // Legacy ContextLoaders don't know how to process classes } - initializers.addAll(0, Arrays.asList(configAttributes.getInitializers())); if (!configAttributes.isInheritLocations()) { break; } } + Set>> initializers = + ApplicationContextInitializerUtils.resolveInitializerClasses(configAttributesList); Set contextCustomizers = getContextCustomizers(testClass, Collections.unmodifiableList(configAttributesList)); @@ -342,8 +342,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot TestPropertySourceUtils.buildMergedTestPropertySources(testClass); MergedContextConfiguration mergedConfig = new MergedContextConfiguration(testClass, StringUtils.toStringArray(locations), ClassUtils.toClassArray(classes), - ApplicationContextInitializerUtils.resolveInitializerClasses(configAttributesList), - ActiveProfilesUtils.resolveActiveProfiles(testClass), + initializers, ActiveProfilesUtils.resolveActiveProfiles(testClass), mergedTestPropertySources.getPropertySourceDescriptors(), mergedTestPropertySources.getProperties(), contextCustomizers, contextLoader, cacheAwareContextLoaderDelegate, parentConfig);