From ea7a1d789e6d07ae18e699c718cbf54dacfb91de Mon Sep 17 00:00:00 2001
From: Sam Brannen <104798+sbrannen@users.noreply.github.com>
Date: Wed, 10 Dec 2025 18:34:25 +0100
Subject: [PATCH] Resolve ContextLoader only once in
AbstractTestContextBootstrapper
Closes gh-35994
---
.../AbstractTestContextBootstrapper.java | 23 +++++++++++--------
1 file changed, 14 insertions(+), 9 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 4075e367d3a..d2f4f1310c0 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
@@ -231,7 +231,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
Class> declaringClass = reversedList.get(0).getDeclaringClass();
mergedConfig = buildMergedContextConfiguration(
- declaringClass, reversedList, parentConfig, cacheAwareContextLoaderDelegate, true);
+ declaringClass, reversedList, null, parentConfig, cacheAwareContextLoaderDelegate, true);
parentConfig = mergedConfig;
}
@@ -242,7 +242,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
else {
return buildMergedContextConfiguration(testClass,
ContextLoaderUtils.resolveContextConfigurationAttributes(testClass),
- null, cacheAwareContextLoaderDelegate, true);
+ null, null, cacheAwareContextLoaderDelegate, true);
}
}
@@ -263,7 +263,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
"Neither @ContextConfiguration nor @ContextHierarchy found for test class [%s]: using %s",
testClass.getSimpleName(), contextLoader.getClass().getSimpleName()));
}
- return buildMergedContextConfiguration(testClass, defaultConfigAttributesList, null,
+ return buildMergedContextConfiguration(testClass, defaultConfigAttributesList, contextLoader, null,
cacheAwareContextLoaderDelegate, false);
}
@@ -277,6 +277,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
* specified test class, ordered bottom-up (i.e., as if we were
* traversing up the class hierarchy and enclosing class hierarchy); never
* {@code null} or empty
+ * @param contextLoader a pre-resolved {@link ContextLoader} to use; may be {@code null}
* @param parentConfig the merged context configuration for the parent application
* context in a context hierarchy, or {@code null} if there is no parent
* @param cacheAwareContextLoaderDelegate the cache-aware context loader delegate to
@@ -294,13 +295,16 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
* @see MergedContextConfiguration
*/
private MergedContextConfiguration buildMergedContextConfiguration(Class> testClass,
- List configAttributesList, @Nullable MergedContextConfiguration parentConfig,
+ List configAttributesList, @Nullable ContextLoader contextLoader,
+ @Nullable MergedContextConfiguration parentConfig,
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate,
boolean requireLocationsClassesOrInitializers) {
Assert.notEmpty(configAttributesList, "ContextConfigurationAttributes list must not be null or empty");
- ContextLoader contextLoader = resolveContextLoader(testClass, configAttributesList);
+ if (contextLoader == null) {
+ contextLoader = resolveContextLoader(testClass, configAttributesList);
+ }
List locations = new ArrayList<>();
List> classes = new ArrayList<>();
List> initializers = new ArrayList<>();
@@ -331,11 +335,12 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
Set contextCustomizers = getContextCustomizers(testClass,
Collections.unmodifiableList(configAttributesList));
+ ContextLoader effectivelyFinalContextLoader = contextLoader;
Assert.state(!(requireLocationsClassesOrInitializers &&
- areAllEmpty(locations, classes, initializers, contextCustomizers)), () -> String.format(
- "%s was unable to detect defaults, and no ApplicationContextInitializers " +
- "or ContextCustomizers were declared for context configuration attributes %s",
- contextLoader.getClass().getSimpleName(), configAttributesList));
+ areAllEmpty(locations, classes, initializers, contextCustomizers)), () -> """
+ %s was unable to detect defaults, and no ApplicationContextInitializers \
+ or ContextCustomizers were declared for context configuration attributes %s\
+ """.formatted(effectivelyFinalContextLoader.getClass().getSimpleName(), configAttributesList));
MergedTestPropertySources mergedTestPropertySources =
TestPropertySourceUtils.buildMergedTestPropertySources(testClass);