diff --git a/org.springframework.test/src/main/java/org/springframework/test/context/ContextLoaderUtils.java b/org.springframework.test/src/main/java/org/springframework/test/context/ContextLoaderUtils.java
index 295ce15d9f..37046eb931 100644
--- a/org.springframework.test/src/main/java/org/springframework/test/context/ContextLoaderUtils.java
+++ b/org.springframework.test/src/main/java/org/springframework/test/context/ContextLoaderUtils.java
@@ -56,63 +56,10 @@ abstract class ContextLoaderUtils {
/* no-op */
}
- /**
- * Resolve the list of {@link ContextConfigurationAttributes configuration
- * attributes} for the supplied {@link Class class} and its superclasses.
- *
Note that the {@link ContextConfiguration#inheritLocations
- * inheritLocations} flag of {@link ContextConfiguration
- * @ContextConfiguration} will be taken into consideration.
- * Specifically, if the inheritLocations
flag is set to
- * true
, configuration attributes defined in the annotated
- * class will be appended to the configuration attributes defined in
- * superclasses.
- * @param clazz the class for which to resolve the configuration attributes (must
- * not be null
)
- * @return the list of configuration attributes for the specified class,
- * including configuration attributes from superclasses if appropriate
- * (never null
)
- * @throws IllegalArgumentException if the supplied class is null
- * or if {@link ContextConfiguration @ContextConfiguration} is not
- * present on the supplied class
- */
- static List resolveContextConfigurationAttributes(Class> clazz) {
- Assert.notNull(clazz, "Class must not be null");
-
- final List attributesList = new ArrayList();
-
- Class annotationType = ContextConfiguration.class;
- Class> declaringClass = AnnotationUtils.findAnnotationDeclaringClass(annotationType, clazz);
- Assert.notNull(declaringClass, String.format(
- "Could not find an 'annotation declaring class' for annotation type [%s] and class [%s]", annotationType,
- clazz));
-
- while (declaringClass != null) {
- ContextConfiguration contextConfiguration = declaringClass.getAnnotation(annotationType);
-
- if (logger.isTraceEnabled()) {
- logger.trace(String.format("Retrieved @ContextConfiguration [%s] for declaring class [%s].",
- contextConfiguration, declaringClass));
- }
-
- ContextConfigurationAttributes attributes = new ContextConfigurationAttributes(declaringClass,
- contextConfiguration);
- if (logger.isTraceEnabled()) {
- logger.trace("Resolved context configuration attributes: " + attributes);
- }
-
- attributesList.add(0, attributes);
-
- declaringClass = contextConfiguration.inheritLocations() ? AnnotationUtils.findAnnotationDeclaringClass(
- annotationType, declaringClass.getSuperclass()) : null;
- }
-
- return attributesList;
- }
-
/**
* Resolve the {@link ContextLoader} {@link Class class} to use for the
- * supplied {@link Class testClass} and {@link ContextConfigurationAttributes}
- * and then instantiate and return that {@code ContextLoader}.
+ * supplied {@link Class testClass} and then instantiate and return that
+ * {@code ContextLoader}.
* If the supplied defaultContextLoaderClassName
is
* null
or empty, the standard
* default context loader class name {@value #DEFAULT_CONTEXT_LOADER_CLASS_NAME}
@@ -120,25 +67,20 @@ abstract class ContextLoaderUtils {
* {@link #resolveContextLoaderClass()}.
* @param testClass the test class for which the {@code ContextLoader}
* should be resolved (must not be null
)
- * @param configAttributesList the resolved configuration attributes for the
- * test class hierarchy
* @param defaultContextLoaderClassName the name of the default
* {@code ContextLoader} class to use (may be null
)
* @return the resolved {@code ContextLoader} for the supplied
* testClass
(never null
)
* @see #resolveContextLoaderClass()
- * @see #resolveContextConfigurationAttributes()
*/
- static ContextLoader resolveContextLoader(Class> testClass,
- List configAttributesList, String defaultContextLoaderClassName) {
+ static ContextLoader resolveContextLoader(Class> testClass, String defaultContextLoaderClassName) {
Assert.notNull(testClass, "Test class must not be null");
- Assert.notEmpty(configAttributesList, "ContextConfigurationAttributes list must not be null or empty");
if (!StringUtils.hasText(defaultContextLoaderClassName)) {
defaultContextLoaderClassName = DEFAULT_CONTEXT_LOADER_CLASS_NAME;
}
- Class extends ContextLoader> contextLoaderClass = resolveContextLoaderClass(testClass, configAttributesList,
+ Class extends ContextLoader> contextLoaderClass = resolveContextLoaderClass(testClass,
defaultContextLoaderClassName);
return (ContextLoader) BeanUtils.instantiateClass(contextLoaderClass);
@@ -146,56 +88,61 @@ abstract class ContextLoaderUtils {
/**
* Resolve the {@link ContextLoader} {@link Class} to use for the supplied
- * {@link ContextConfigurationAttributes} list.
- * This method will iterate over the supplied configuration attributes
- * and execute the following algorithm:
+ * {@link Class testClass}.
*
- * - If {@link ContextConfigurationAttributes#getContextLoaderClass()}
- * returns an explicit implementation class, that class will be returned.
- * - If an explicit {@code ContextLoader} implementation class is not
- * specified, the next {@link ContextConfigurationAttributes} instance in
- * the supplied list will be processed; go to step #1.
- * - If no explicit
loader
class is found after processing
- * all {@link ContextConfigurationAttributes} instances, an attempt will be
- * made to load and return the class with the supplied
- * defaultContextLoaderClassName
.
+ * - If the {@link ContextConfiguration#loader() loader} attribute of
+ * {@link ContextConfiguration @ContextConfiguration} is configured
+ * with an explicit class, that class will be returned.
+ * - If a
loader
class is not specified, the class hierarchy
+ * will be traversed to find a parent class annotated with
+ * {@code @ContextConfiguration}; go to step #1.
+ * - If no explicit
loader
class is found after traversing
+ * the class hierarchy, an attempt will be made to load and return the class
+ * with the supplied defaultContextLoaderClassName
.
*
* @param testClass the class for which to resolve the {@code ContextLoader}
- * class; used solely for logging purposes; must not be null
- * @param configAttributesList the resolved configuration attributes for the
- * test class hierarchy; must not be null
or empty
+ * class; must not be null
* @param defaultContextLoaderClassName the name of the default
* {@code ContextLoader} class to use; must not be null
or empty
- * @return the {@code ContextLoader} class to use for the specified class
- * (never null
)
+ * @return the {@code ContextLoader} class to use for the supplied test class
* @throws IllegalArgumentException if {@code @ContextConfiguration} is not
- * present on the supplied test class
- * @see #resolveContextLoader()
- * @see #resolveContextConfigurationAttributes()
+ * present on the supplied test class
+ * @throws IllegalStateException if the default {@code ContextLoader} class
+ * could not be loaded
*/
@SuppressWarnings("unchecked")
static Class extends ContextLoader> resolveContextLoaderClass(Class> testClass,
- List configAttributesList, String defaultContextLoaderClassName) {
+ String defaultContextLoaderClassName) {
Assert.notNull(testClass, "Class must not be null");
- Assert.notEmpty(configAttributesList, "ContextConfigurationAttributes list must not be null or empty");
Assert.hasText(defaultContextLoaderClassName, "Default ContextLoader class name must not be null or empty");
- for (ContextConfigurationAttributes configAttributes : configAttributesList) {
+ Class annotationType = ContextConfiguration.class;
+ Class> declaringClass = AnnotationUtils.findAnnotationDeclaringClass(annotationType, testClass);
+ Assert.notNull(declaringClass, String.format(
+ "Could not find an 'annotation declaring class' for annotation type [%s] and test class [%s]",
+ annotationType, testClass));
+
+ while (declaringClass != null) {
+ ContextConfiguration contextConfiguration = declaringClass.getAnnotation(annotationType);
+
if (logger.isTraceEnabled()) {
logger.trace(String.format(
- "Processing ContextLoader for context configuration attributes [%s] and test class [%s]",
- configAttributes, testClass));
+ "Processing ContextLoader for @ContextConfiguration [%s] and declaring class [%s]",
+ contextConfiguration, declaringClass));
}
- Class extends ContextLoader> contextLoaderClass = configAttributes.getContextLoaderClass();
+ Class extends ContextLoader> contextLoaderClass = contextConfiguration.loader();
if (!ContextLoader.class.equals(contextLoaderClass)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format(
- "Found explicit ContextLoader class [%s] for context configuration attributes [%s] and test class [%s]",
- contextLoaderClass, configAttributes, testClass));
+ "Found explicit ContextLoader class [%s] for @ContextConfiguration [%s] and declaring class [%s]",
+ contextLoaderClass, contextConfiguration, declaringClass));
}
return contextLoaderClass;
}
+
+ declaringClass = AnnotationUtils.findAnnotationDeclaringClass(annotationType,
+ declaringClass.getSuperclass());
}
try {
@@ -213,6 +160,58 @@ abstract class ContextLoaderUtils {
}
}
+ /**
+ * Resolve the list of {@link ContextConfigurationAttributes configuration
+ * attributes} for the supplied {@link Class class} and its superclasses.
+ * Note that the {@link ContextConfiguration#inheritLocations
+ * inheritLocations} flag of {@link ContextConfiguration
+ * @ContextConfiguration} will be taken into consideration.
+ * Specifically, if the inheritLocations
flag is set to
+ * true
, configuration attributes defined in the annotated
+ * class will be appended to the configuration attributes defined in
+ * superclasses.
+ * @param clazz the class for which to resolve the configuration attributes (must
+ * not be null
)
+ * @return the list of configuration attributes for the specified class,
+ * including configuration attributes from superclasses if appropriate
+ * (never null
)
+ * @throws IllegalArgumentException if the supplied class is null
or
+ * if {@code @ContextConfiguration} is not present on the supplied class
+ */
+ static List resolveContextConfigurationAttributes(Class> clazz) {
+ Assert.notNull(clazz, "Class must not be null");
+
+ final List attributesList = new ArrayList();
+
+ Class annotationType = ContextConfiguration.class;
+ Class> declaringClass = AnnotationUtils.findAnnotationDeclaringClass(annotationType, clazz);
+ Assert.notNull(declaringClass, String.format(
+ "Could not find an 'annotation declaring class' for annotation type [%s] and class [%s]", annotationType,
+ clazz));
+
+ while (declaringClass != null) {
+ ContextConfiguration contextConfiguration = declaringClass.getAnnotation(annotationType);
+
+ if (logger.isTraceEnabled()) {
+ logger.trace(String.format("Retrieved @ContextConfiguration [%s] for declaring class [%s].",
+ contextConfiguration, declaringClass));
+ }
+
+ ContextConfigurationAttributes attributes = new ContextConfigurationAttributes(declaringClass,
+ contextConfiguration);
+ if (logger.isTraceEnabled()) {
+ logger.trace("Resolved context configuration attributes: " + attributes);
+ }
+
+ attributesList.add(0, attributes);
+
+ declaringClass = contextConfiguration.inheritLocations() ? AnnotationUtils.findAnnotationDeclaringClass(
+ annotationType, declaringClass.getSuperclass()) : null;
+ }
+
+ return attributesList;
+ }
+
/**
* Resolve active bean definition profiles for the supplied {@link Class}.
* Note that the {@link ActiveProfiles#inheritProfiles inheritProfiles}
@@ -286,8 +285,8 @@ abstract class ContextLoaderUtils {
* @param defaultContextLoaderClassName the name of the default
* {@code ContextLoader} class to use (may be null
)
* @return the merged context configuration
- * @see #resolveContextConfigurationAttributes()
* @see #resolveContextLoader()
+ * @see #resolveContextConfigurationAttributes()
* @see SmartContextLoader#processContextConfiguration()
* @see ContextLoader#processLocations()
* @see #resolveActiveProfiles()
@@ -296,16 +295,8 @@ abstract class ContextLoaderUtils {
static MergedContextConfiguration buildMergedContextConfiguration(Class> testClass,
String defaultContextLoaderClassName) {
- List configAttributesList = resolveContextConfigurationAttributes(testClass);
-
- ContextLoader contextLoader = resolveContextLoader(testClass, configAttributesList,
- defaultContextLoaderClassName);
-
- // Algorithm:
- // - iterate over config attributes
- // -- let loader process locations
- // -- let loader process classes, if it's a SmartContextLoader
-
+ final ContextLoader contextLoader = resolveContextLoader(testClass, defaultContextLoaderClassName);
+ final List configAttributesList = resolveContextConfigurationAttributes(testClass);
final List locationsList = new ArrayList();
final List> classesList = new ArrayList>();