From 9a56deb2833cfc72f259af5fb6c849feb46e729b Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Fri, 17 Jun 2011 21:49:06 +0000 Subject: [PATCH] [SPR-8386] SmartContextLoader enhancements: - introduced processContextConfigurationAttributes() method in SmartContextLoader SPI - refactored AnnotationConfigContextLoader, AbstractContextLoader, AbstractGenericContextLoader, ContextLoaderUtils, and TestContext implementations to take advantage of the SmartContextLoader SPI, MergedContextConfiguration, and ContextConfigurationAttributes - deleted ResourceTypeAwareContextLoader - deleted ContextLoaderUtils.LocationsResolver and implementations - moved context key generation from TestContext to MergedContextConfiguration --- .../ContextConfigurationAttributes.java | 41 ++- .../test/context/ContextLoaderUtils.java | 327 +++++++----------- .../context/MergedContextConfiguration.java | 32 +- .../ResourceTypeAwareContextLoader.java | 69 ---- .../test/context/SmartContextLoader.java | 9 +- .../test/context/TestContext.java | 39 +-- .../support/AbstractContextLoader.java | 23 +- .../support/AbstractGenericContextLoader.java | 30 +- .../AnnotationConfigContextLoader.java | 139 ++++---- .../test/context/ContextLoaderUtilsTests.java | 28 +- .../context/TestContextCacheKeyTests.java | 2 +- .../junit4/SpringJUnit4SuiteTests.java | 30 +- 12 files changed, 317 insertions(+), 452 deletions(-) delete mode 100644 org.springframework.test/src/main/java/org/springframework/test/context/ResourceTypeAwareContextLoader.java diff --git a/org.springframework.test/src/main/java/org/springframework/test/context/ContextConfigurationAttributes.java b/org.springframework.test/src/main/java/org/springframework/test/context/ContextConfigurationAttributes.java index ba68d37a741..b09c44cb42f 100644 --- a/org.springframework.test/src/main/java/org/springframework/test/context/ContextConfigurationAttributes.java +++ b/org.springframework.test/src/main/java/org/springframework/test/context/ContextConfigurationAttributes.java @@ -34,13 +34,13 @@ public class ContextConfigurationAttributes { private final Class declaringClass; - private final String[] locations; + private String[] locations; - private final Class[] classes; + private Class[] classes; private final boolean inheritLocations; - private final Class contextLoader; + private final Class contextLoaderClass; /** @@ -72,9 +72,6 @@ public class ContextConfigurationAttributes { /** * TODO Document ContextConfigurationAttributes constructor. - * - * @param declaringClass - * @param contextConfiguration */ public ContextConfigurationAttributes(Class declaringClass, ContextConfiguration contextConfiguration) { this(declaringClass, resolveLocations(declaringClass, contextConfiguration), contextConfiguration.classes(), @@ -83,20 +80,14 @@ public class ContextConfigurationAttributes { /** * TODO Document ContextConfigurationAttributes constructor. - * - * @param declaringClass - * @param locations - * @param classes - * @param inheritLocations - * @param contextLoader */ public ContextConfigurationAttributes(Class declaringClass, String[] locations, Class[] classes, - boolean inheritLocations, Class contextLoader) { + boolean inheritLocations, Class contextLoaderClass) { this.declaringClass = declaringClass; this.locations = locations; this.classes = classes; this.inheritLocations = inheritLocations; - this.contextLoader = contextLoader; + this.contextLoaderClass = contextLoaderClass; } /** @@ -113,6 +104,13 @@ public class ContextConfigurationAttributes { return this.locations; } + /** + * TODO Document setLocations(). + */ + public void setLocations(String[] locations) { + this.locations = locations; + } + /** * TODO Document getClasses(). */ @@ -120,6 +118,13 @@ public class ContextConfigurationAttributes { return this.classes; } + /** + * TODO Document setClasses(). + */ + public void setClasses(Class[] classes) { + this.classes = classes; + } + /** * TODO Document isInheritLocations(). */ @@ -128,10 +133,10 @@ public class ContextConfigurationAttributes { } /** - * TODO Document getContextLoader(). + * TODO Document getContextLoaderClass(). */ - public Class getContextLoader() { - return this.contextLoader; + public Class getContextLoaderClass() { + return this.contextLoaderClass; } /** @@ -144,7 +149,7 @@ public class ContextConfigurationAttributes { .append("locations", ObjectUtils.nullSafeToString(this.locations))// .append("classes", ObjectUtils.nullSafeToString(this.classes))// .append("inheritLocations", this.inheritLocations)// - .append("contextLoader", this.contextLoader)// + .append("contextLoaderClass", this.contextLoaderClass)// .toString(); } 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 537ed649507..ddf77066abd 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 @@ -25,10 +25,9 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeanUtils; -import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.test.context.ResourceTypeAwareContextLoader.ResourceType; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -40,21 +39,53 @@ import org.springframework.util.StringUtils; * @since 3.1 * @see ContextLoader * @see ContextConfiguration + * @see ContextConfigurationAttributes * @see ActiveProfiles * @see MergedContextConfiguration */ abstract class ContextLoaderUtils { - // TODO Consider refactoring ContextLoaderUtils into a stateful - // ContextLoaderResolver. - private static final Log logger = LogFactory.getLog(ContextLoaderUtils.class); private static final String STANDARD_DEFAULT_CONTEXT_LOADER_CLASS_NAME = "org.springframework.test.context.support.GenericXmlContextLoader"; - private static final ResourcePathLocationsResolver resourcePathLocationsResolver = new ResourcePathLocationsResolver(); - private static final ClassNameLocationsResolver classNameLocationsResolver = new ClassNameLocationsResolver(); + /** + * TODO Document resolveContextConfigurationAttributes(). + */ + 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; + } /** * Resolves the {@link ContextLoader} {@link Class} to use for the @@ -66,22 +97,27 @@ abstract class ContextLoaderUtils { * default context loader class name ({@value #STANDARD_DEFAULT_CONTEXT_LOADER_CLASS_NAME}) * will be used. For details on the class resolution process, see * {@link #resolveContextLoaderClass(Class, String)}. + * * @param testClass the test class for which the ContextLoader * should be resolved (must not be null) + * @param configAttributesList TODO Document parameter * @param defaultContextLoaderClassName the name of the default * ContextLoader class to use (may be null) + * * @return the resolved ContextLoader for the supplied * testClass (never null) * @see #resolveContextLoaderClass(Class, String) */ - static ContextLoader resolveContextLoader(Class testClass, String defaultContextLoaderClassName) { + static ContextLoader resolveContextLoader(Class testClass, + List configAttributesList, 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 = STANDARD_DEFAULT_CONTEXT_LOADER_CLASS_NAME; } - Class contextLoaderClass = resolveContextLoaderClass(testClass, + Class contextLoaderClass = resolveContextLoaderClass(testClass, configAttributesList, defaultContextLoaderClassName); return (ContextLoader) BeanUtils.instantiateClass(contextLoaderClass); @@ -103,52 +139,46 @@ abstract class ContextLoaderUtils { * with the supplied defaultContextLoaderClassName. * * - * @param clazz the class for which to resolve the ContextLoader + * @param testClass the class for which to resolve the ContextLoader * class; must not be null + * @param configAttributesList TODO Document parameter * @param defaultContextLoaderClassName the name of the default * ContextLoader class to use; must not be null or empty + * * @return the ContextLoader class to use for the specified class * (never null) * @throws IllegalArgumentException if {@link ContextConfiguration * @ContextConfiguration} is not present on the supplied class */ @SuppressWarnings("unchecked") - static Class resolveContextLoaderClass(Class clazz, String defaultContextLoaderClassName) { - Assert.notNull(clazz, "Class must not be null"); + static Class resolveContextLoaderClass(Class testClass, + List configAttributesList, 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"); - 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); + for (ContextConfigurationAttributes configAttributes : configAttributesList) { if (logger.isTraceEnabled()) { - logger.trace("Processing ContextLoader for @ContextConfiguration [" + contextConfiguration - + "] and declaring class [" + declaringClass + "]"); + logger.trace(String.format( + "Processing ContextLoader for context configuration attributes [%s] and test class [%s]", + configAttributes, testClass)); } - Class contextLoaderClass = contextConfiguration.loader(); + Class contextLoaderClass = configAttributes.getContextLoaderClass(); if (!ContextLoader.class.equals(contextLoaderClass)) { if (logger.isDebugEnabled()) { - logger.debug("Found explicit ContextLoader [" + contextLoaderClass - + "] for @ContextConfiguration [" + contextConfiguration + "] and declaring class [" - + declaringClass + "]"); + logger.debug(String.format( + "Found explicit ContextLoader class [%s] for context configuration attributes [%s] and test class [%s]", + contextLoaderClass, configAttributes, testClass)); } return contextLoaderClass; } - - declaringClass = AnnotationUtils.findAnnotationDeclaringClass(annotationType, - declaringClass.getSuperclass()); } try { if (logger.isTraceEnabled()) { - ContextConfiguration contextConfiguration = clazz.getAnnotation(annotationType); - logger.trace("Using default ContextLoader class [" + defaultContextLoaderClassName - + "] for @ContextConfiguration [" + contextConfiguration + "] and class [" + clazz + "]"); + logger.trace(String.format("Using default ContextLoader class [%s] for test class [%s]", + defaultContextLoaderClassName, testClass)); } return (Class) ContextLoaderUtils.class.getClassLoader().loadClass( defaultContextLoaderClassName); @@ -160,65 +190,6 @@ abstract class ContextLoaderUtils { } } - /** - * Resolves {@link ApplicationContext} resource locations for the supplied - * {@link Class class}, using the supplied {@link ContextLoader} to - * {@link ContextLoader#processLocations(Class, String...) process} the - * locations. - * - *

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, locations defined in the annotated class will be - * appended to the locations defined in superclasses. - * - * @param contextLoader the ContextLoader to use for processing the - * locations (must not be null) - * @param clazz the class for which to resolve the resource locations (must - * not be null) - * @return the list of ApplicationContext resource locations for the - * specified class, including locations from superclasses if appropriate - * (never null) - * @throws IllegalArgumentException if {@link ContextConfiguration - * @ContextConfiguration} is not present on the supplied class - */ - static String[] resolveContextLocations(ContextLoader contextLoader, Class clazz) { - Assert.notNull(contextLoader, "ContextLoader must not be null"); - Assert.notNull(clazz, "Class must not be null"); - - boolean processConfigurationClasses = (contextLoader instanceof ResourceTypeAwareContextLoader) - && ResourceType.CLASSES == ((ResourceTypeAwareContextLoader) contextLoader).getResourceType(); - LocationsResolver locationsResolver = processConfigurationClasses ? classNameLocationsResolver - : resourcePathLocationsResolver; - - 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)); - - final List locationsList = new ArrayList(); - - while (declaringClass != null) { - ContextConfiguration contextConfiguration = declaringClass.getAnnotation(annotationType); - - if (logger.isTraceEnabled()) { - logger.trace(String.format("Retrieved @ContextConfiguration [%s] for declaring class [%s].", - contextConfiguration, declaringClass)); - } - - String[] resolvedLocations = locationsResolver.resolveLocations(contextConfiguration, declaringClass); - String[] processedLocations = contextLoader.processLocations(declaringClass, resolvedLocations); - locationsList.addAll(0, Arrays.asList(processedLocations)); - - declaringClass = contextConfiguration.inheritLocations() ? AnnotationUtils.findAnnotationDeclaringClass( - annotationType, declaringClass.getSuperclass()) : null; - } - - return StringUtils.toStringArray(locationsList); - } - /** * Resolves active bean definition profiles for the supplied * {@link Class class}. @@ -231,6 +202,7 @@ abstract class ContextLoaderUtils { * * @param clazz the class for which to resolve the active profiles (must * not be null) + * * @return the set of active profiles for the specified class, including * active profiles from superclasses if appropriate (never null) */ @@ -284,136 +256,77 @@ abstract class ContextLoaderUtils { return StringUtils.toStringArray(activeProfiles); } - /** - * TODO Document resolveContextConfigurationAttributes(). - * - * @param clazz - * @return + /* + * Resolves {@link ApplicationContext} resource locations for the supplied + * {@link Class class}, using the supplied {@link ContextLoader} to {@link + * ContextLoader#processLocations(Class, String...) process} the locations. + * + *

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, locations defined in the annotated class will be + * appended to the locations defined in superclasses. + * + * @param contextLoader the ContextLoader to use for processing the + * locations (must not be null) + * + * @param clazz the class for which to resolve the resource locations (must + * not be null) + * + * @return the list of ApplicationContext resource locations for the + * specified class, including locations from superclasses if appropriate + * (never null) + * + * @throws IllegalArgumentException 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; - } /** * TODO Document buildMergedContextConfiguration(). - * - * @param testClass - * @param defaultContextLoaderClassName - * @return */ static MergedContextConfiguration buildMergedContextConfiguration(Class testClass, String defaultContextLoaderClassName) { - ContextLoader contextLoader = resolveContextLoader(testClass, defaultContextLoaderClassName); + List configAttributesList = resolveContextConfigurationAttributes(testClass); - // TODO Merge locations from List - String[] locations = resolveContextLocations(contextLoader, testClass); + ContextLoader contextLoader = resolveContextLoader(testClass, configAttributesList, + defaultContextLoaderClassName); - // TODO Merge classes from List - Class[] classes = {}; + // Algorithm: + // - iterate over config attributes + // -- let loader process locations + // -- let loader process classes, if it's a SmartContextLoader + final List locationsList = new ArrayList(); + final List> classesList = new ArrayList>(); + + for (ContextConfigurationAttributes configAttributes : configAttributesList) { + if (logger.isTraceEnabled()) { + logger.trace(String.format( + "Processing locations and classes for context configuration attributes [%s]", configAttributes)); + } + + if (contextLoader instanceof SmartContextLoader) { + SmartContextLoader smartContextLoader = (SmartContextLoader) contextLoader; + // TODO Decide on mutability of locations and classes properties + smartContextLoader.processContextConfigurationAttributes(configAttributes); + locationsList.addAll(Arrays.asList(configAttributes.getLocations())); + classesList.addAll(Arrays.asList(configAttributes.getClasses())); + } + else { + String[] processedLocations = contextLoader.processLocations(configAttributes.getDeclaringClass(), + configAttributes.getLocations()); + locationsList.addAll(Arrays.asList(processedLocations)); + // Legacy ContextLoaders don't know how to process classes + } + } + + String[] locations = StringUtils.toStringArray(locationsList); + Class[] classes = ClassUtils.toClassArray(classesList); String[] activeProfiles = resolveActiveProfiles(testClass); return new MergedContextConfiguration(testClass, locations, classes, activeProfiles, contextLoader); } - - /** - * Strategy interface for resolving application context resource locations. - * - *

The semantics of the resolved locations are implementation-dependent. - */ - private static interface LocationsResolver { - - /** - * Resolves application context resource locations for the supplied - * {@link ContextConfiguration} annotation and the class which declared it. - * @param contextConfiguration the ContextConfiguration - * for which to resolve resource locations - * @param declaringClass the class that declared ContextConfiguration - * @return an array of application context resource locations - * (can be null or empty) - */ - String[] resolveLocations(ContextConfiguration contextConfiguration, Class declaringClass); - } - - /** - * LocationsResolver that resolves locations as Strings, - * which are assumed to be path-based resources. - */ - private static final class ResourcePathLocationsResolver implements LocationsResolver { - - /** - * Resolves path-based resources from the {@link ContextConfiguration#locations() locations} - * and {@link ContextConfiguration#value() value} attributes of the supplied - * {@link ContextConfiguration} annotation. - * - *

Ignores the {@link ContextConfiguration#classes() classes} attribute. - * @throws IllegalStateException if both the locations and value - * attributes have been declared - */ - public String[] resolveLocations(ContextConfiguration contextConfiguration, Class declaringClass) { - return ContextConfigurationAttributes.resolveLocations(declaringClass, contextConfiguration); - } - } - - /** - * LocationsResolver that converts classes to fully qualified class names. - */ - private static final class ClassNameLocationsResolver implements LocationsResolver { - - /** - * Resolves class names from the {@link ContextConfiguration#classes() classes} - * attribute of the supplied {@link ContextConfiguration} annotation. - * - *

Ignores the {@link ContextConfiguration#locations() locations} - * and {@link ContextConfiguration#value() value} attributes. - */ - public String[] resolveLocations(ContextConfiguration contextConfiguration, Class declaringClass) { - - String[] classNames = null; - - Class[] configClasses = contextConfiguration.classes(); - if (!ObjectUtils.isEmpty(configClasses)) { - classNames = new String[configClasses.length]; - - for (int i = 0; i < configClasses.length; i++) { - classNames[i] = configClasses[i].getName(); - } - } - - return classNames; - } - } - } diff --git a/org.springframework.test/src/main/java/org/springframework/test/context/MergedContextConfiguration.java b/org.springframework.test/src/main/java/org/springframework/test/context/MergedContextConfiguration.java index a7836dd2b22..564e1702e5d 100644 --- a/org.springframework.test/src/main/java/org/springframework/test/context/MergedContextConfiguration.java +++ b/org.springframework.test/src/main/java/org/springframework/test/context/MergedContextConfiguration.java @@ -44,6 +44,8 @@ public class MergedContextConfiguration { private final ContextLoader contextLoader; + private final String contextKey; + private static String[] processLocations(String[] locations) { return locations == null ? new String[] {} : locations; @@ -65,14 +67,23 @@ public class MergedContextConfiguration { return StringUtils.toStringArray(sortedProfilesSet); } + /** + * Generates a context key from the supplied values. + */ + private static String generateContextKey(String[] locations, Class[] classes, String[] activeProfiles, + ContextLoader contextLoader) { + + String locationsKey = ObjectUtils.nullSafeToString(locations); + String classesKey = ObjectUtils.nullSafeToString(classes); + String activeProfilesKey = ObjectUtils.nullSafeToString(activeProfiles); + String contextLoaderKey = contextLoader == null ? "null" : contextLoader.getClass().getName(); + + return String.format("locations = [%s], classes = [%s], activeProfiles = [%s], contextLoader = [%s]", + locationsKey, classesKey, activeProfilesKey, contextLoaderKey); + } + /** * TODO Document MergedContextConfiguration constructor. - * - * @param testClass - * @param locations - * @param classes - * @param activeProfiles - * @param contextLoader */ public MergedContextConfiguration(Class testClass, String[] locations, Class[] classes, String[] activeProfiles, ContextLoader contextLoader) { @@ -81,6 +92,7 @@ public class MergedContextConfiguration { this.classes = processClasses(classes); this.activeProfiles = processActiveProfiles(activeProfiles); this.contextLoader = contextLoader; + this.contextKey = generateContextKey(this.locations, this.classes, this.activeProfiles, this.contextLoader); } /** @@ -118,6 +130,13 @@ public class MergedContextConfiguration { return this.contextLoader; } + /** + * TODO Document getContextKey(). + */ + public String getContextKey() { + return this.contextKey; + } + /** * TODO Document overridden toString(). */ @@ -129,6 +148,7 @@ public class MergedContextConfiguration { .append("classes", ObjectUtils.nullSafeToString(this.classes))// .append("activeProfiles", ObjectUtils.nullSafeToString(this.activeProfiles))// .append("contextLoader", this.contextLoader)// + .append("contextKey", this.contextKey)// .toString(); } diff --git a/org.springframework.test/src/main/java/org/springframework/test/context/ResourceTypeAwareContextLoader.java b/org.springframework.test/src/main/java/org/springframework/test/context/ResourceTypeAwareContextLoader.java deleted file mode 100644 index dd39037f9e3..00000000000 --- a/org.springframework.test/src/main/java/org/springframework/test/context/ResourceTypeAwareContextLoader.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.test.context; - -/** - * Extension of the {@link ContextLoader} API for context loaders that - * are aware of the type of context configuration resources that they - * support. - * - *

Prior to Spring 3.1, context loaders supported only String-based - * resource locations; as of Spring 3.1 context loaders may choose to - * support either String-based or Class-based resources (but not both). - * - *

TODO Document how classes are converted into String[] locations - * and passed into the corresponding methods in the ContextLoader API. - * - *

If a context loader does not implement this interface it is assumed - * that the loader supports String-based resource locations. - * - * @author Sam Brannen - * @since 3.1 - */ -public interface ResourceTypeAwareContextLoader extends ContextLoader { - - /** - * Enumeration of context configuration resource types that a given - * ContextLoader can support. - * - *

The enum constants have a one-to-one correlation to attributes - * of the {@link ContextConfiguration} annotation. - */ - public static enum ResourceType { - - /** - * String-based resource locations. - * @see ContextConfiguration#locations - * @see ContextConfiguration#value - */ - LOCATIONS, - - /** - * Configuration class resources. - * @see ContextConfiguration#classes - */ - CLASSES; - - }; - - - /** - * @return the context configuration resource type supported by this ContextLoader - */ - ResourceType getResourceType(); - -} diff --git a/org.springframework.test/src/main/java/org/springframework/test/context/SmartContextLoader.java b/org.springframework.test/src/main/java/org/springframework/test/context/SmartContextLoader.java index c2ba977130b..abb847f72a1 100644 --- a/org.springframework.test/src/main/java/org/springframework/test/context/SmartContextLoader.java +++ b/org.springframework.test/src/main/java/org/springframework/test/context/SmartContextLoader.java @@ -26,12 +26,13 @@ import org.springframework.context.ApplicationContext; */ public interface SmartContextLoader extends ContextLoader { + /** + * TODO Document processContextConfigurationAttributes(). + */ + void processContextConfigurationAttributes(ContextConfigurationAttributes configAttributes); + /** * TODO Document loadContext(). - * - * @param mergedContextConfiguration - * @return - * @throws Exception */ ApplicationContext loadContext(MergedContextConfiguration mergedContextConfiguration) throws Exception; diff --git a/org.springframework.test/src/main/java/org/springframework/test/context/TestContext.java b/org.springframework.test/src/main/java/org/springframework/test/context/TestContext.java index de69d6ae62c..0d3704ed288 100644 --- a/org.springframework.test/src/main/java/org/springframework/test/context/TestContext.java +++ b/org.springframework.test/src/main/java/org/springframework/test/context/TestContext.java @@ -24,11 +24,10 @@ import org.springframework.context.ApplicationContext; import org.springframework.core.AttributeAccessorSupport; import org.springframework.core.style.ToStringCreator; import org.springframework.util.Assert; -import org.springframework.util.ObjectUtils; /** - * TestContext encapsulates the context in which a test is executed, agnostic of - * the actual testing framework in use. + * TestContext encapsulates the context in which a test is executed, + * agnostic of the actual testing framework in use. * * @author Sam Brannen * @author Juergen Hoeller @@ -42,8 +41,6 @@ public class TestContext extends AttributeAccessorSupport { private final ContextCache contextCache; - private final String contextKey; - private final MergedContextConfiguration mergedContextConfiguration; private final Class testClass; @@ -69,8 +66,8 @@ public class TestContext extends AttributeAccessorSupport { * and {@link ContextCache context cache} and parse the corresponding * {@link ContextConfiguration @ContextConfiguration} annotation, if * present. - *

If the supplied class name for the default ContextLoader is - * null or empty and no ContextLoader + *

If the supplied class name for the default ContextLoader + * is null or empty and no ContextLoader * class is explicitly supplied via the * @ContextConfiguration annotation, a * {@link org.springframework.test.context.support.GenericXmlContextLoader @@ -106,14 +103,13 @@ public class TestContext extends AttributeAccessorSupport { } this.contextCache = contextCache; - this.contextKey = generateContextKey(mergedContextConfiguration); this.mergedContextConfiguration = mergedContextConfiguration; this.testClass = testClass; } /** * Load an ApplicationContext for this test context using the - * configured ContextLoader and resource locations. + * configured ContextLoader and configuration attributes. * @throws Exception if an error occurs while loading the application context */ private ApplicationContext loadApplicationContext() throws Exception { @@ -137,26 +133,6 @@ public class TestContext extends AttributeAccessorSupport { return applicationContext; } - /** - * Generates a context key from information stored in the - * {@link MergedContextConfiguration} for this TestContext. - */ - private String generateContextKey(MergedContextConfiguration mergedContextConfiguration) { - - String[] locations = mergedContextConfiguration.getLocations(); - Class[] classes = mergedContextConfiguration.getClasses(); - String[] activeProfiles = mergedContextConfiguration.getActiveProfiles(); - ContextLoader contextLoader = mergedContextConfiguration.getContextLoader(); - - String locationsKey = ObjectUtils.nullSafeToString(locations); - String classesKey = ObjectUtils.nullSafeToString(classes); - String activeProfilesKey = ObjectUtils.nullSafeToString(activeProfiles); - String contextLoaderKey = contextLoader == null ? "null" : contextLoader.getClass().getName(); - - return String.format("locations = [%s], classes = [%s], activeProfiles = [%s], contextLoader = [%s]", - locationsKey, classesKey, activeProfilesKey, contextLoaderKey); - } - /** * Get the {@link ApplicationContext application context} for this test * context, possibly cached. @@ -165,6 +141,7 @@ public class TestContext extends AttributeAccessorSupport { * application context */ public ApplicationContext getApplicationContext() { + String contextKey = mergedContextConfiguration.getContextKey(); synchronized (contextCache) { ApplicationContext context = contextCache.get(contextKey); if (context == null) { @@ -239,7 +216,9 @@ public class TestContext extends AttributeAccessorSupport { * replacing a bean definition). */ public void markApplicationContextDirty() { - contextCache.setDirty(contextKey); + synchronized (contextCache) { + contextCache.setDirty(mergedContextConfiguration.getContextKey()); + } } /** diff --git a/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractContextLoader.java b/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractContextLoader.java index 03c61e56ff0..e5f77a6cc19 100644 --- a/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractContextLoader.java +++ b/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractContextLoader.java @@ -18,8 +18,8 @@ package org.springframework.test.context.support; import org.springframework.context.ApplicationContext; import org.springframework.core.io.support.ResourcePatternUtils; +import org.springframework.test.context.ContextConfigurationAttributes; import org.springframework.test.context.ContextLoader; -import org.springframework.test.context.ResourceTypeAwareContextLoader; import org.springframework.test.context.SmartContextLoader; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -39,7 +39,17 @@ import org.springframework.util.StringUtils; * @see #generateDefaultLocations * @see #modifyLocations */ -public abstract class AbstractContextLoader implements SmartContextLoader, ResourceTypeAwareContextLoader { +public abstract class AbstractContextLoader implements SmartContextLoader { + + /** + * TODO Document processContextConfigurationAttributes(). + */ + public void processContextConfigurationAttributes(ContextConfigurationAttributes configAttributes) { + String[] processedLocations = processLocations(configAttributes.getDeclaringClass(), + configAttributes.getLocations()); + + configAttributes.setLocations(processedLocations); + } /** * If the supplied locations are null or @@ -142,13 +152,4 @@ public abstract class AbstractContextLoader implements SmartContextLoader, Resou */ protected abstract String getResourceSuffix(); - /** - * The default implementation returns {@link ResourceType#LOCATIONS}. - *

Can be overridden by subclasses. - * @since 3.1 - */ - public ResourceType getResourceType() { - return ResourceType.LOCATIONS; - } - } diff --git a/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java b/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java index 9fbb46c223d..c6aac51f74e 100644 --- a/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java +++ b/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java @@ -20,12 +20,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.support.BeanDefinitionReader; import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigUtils; import org.springframework.context.support.GenericApplicationContext; import org.springframework.test.context.MergedContextConfiguration; -import org.springframework.util.Assert; +import org.springframework.test.context.SmartContextLoader; import org.springframework.util.StringUtils; /** @@ -49,25 +48,21 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader /** - * TODO Document loadContext(). + * TODO Document loadContext(MergedContextConfiguration). * - * @see org.springframework.test.context.SmartContextLoader#loadContext(org.springframework.test.context.MergedContextConfiguration) + * @see SmartContextLoader#loadContext(MergedContextConfiguration) */ - public final ApplicationContext loadContext(MergedContextConfiguration mergedContextConfiguration) throws Exception { + public final ConfigurableApplicationContext loadContext(MergedContextConfiguration mergedContextConfiguration) + throws Exception { if (logger.isDebugEnabled()) { logger.debug(String.format("Loading ApplicationContext for merged context configuration [%s].", mergedContextConfiguration)); } - - String[] locations = mergedContextConfiguration.getLocations(); - Assert.notNull(locations, "Can not load an ApplicationContext with a NULL 'locations' array. " - + "Consider annotating your test class with @ContextConfiguration."); - GenericApplicationContext context = new GenericApplicationContext(); context.getEnvironment().setActiveProfiles(mergedContextConfiguration.getActiveProfiles()); prepareContext(context); customizeBeanFactory(context.getDefaultListableBeanFactory()); - loadBeanDefinitions(context, locations); + loadBeanDefinitions(context, mergedContextConfiguration); AnnotationConfigUtils.registerAnnotationConfigProcessors(context); customizeContext(context); context.refresh(); @@ -84,7 +79,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader * prepare the context. *

  • Calls {@link #customizeBeanFactory(DefaultListableBeanFactory)} to * allow for customizing the context's DefaultListableBeanFactory.
  • - *
  • Delegates to {@link #loadBeanDefinitions(GenericApplicationContext, String...)} + *
  • TODO Update/revert documentation... Delegates to {@link #loadBeanDefinitions(GenericApplicationContext, String...)} * to populate the context from the specified config locations.
  • *
  • Delegates to {@link AnnotationConfigUtils} for * {@link AnnotationConfigUtils#registerAnnotationConfigProcessors registering} @@ -106,7 +101,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader GenericApplicationContext context = new GenericApplicationContext(); prepareContext(context); customizeBeanFactory(context.getDefaultListableBeanFactory()); - loadBeanDefinitions(context, locations); + createBeanDefinitionReader(context).loadBeanDefinitions(locations); AnnotationConfigUtils.registerAnnotationConfigProcessors(context); customizeContext(context); context.refresh(); @@ -154,12 +149,13 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader * and override this method to provide a custom strategy for loading or * registering bean definitions. * @param context the context into which the bean definitions should be loaded - * @param locations the resource locations from which to load the bean definitions + * @param mergedContextConfiguration TODO Document parameters. * @since 3.1 * @see #loadContext */ - protected void loadBeanDefinitions(GenericApplicationContext context, String... locations) { - createBeanDefinitionReader(context).loadBeanDefinitions(locations); + protected void loadBeanDefinitions(GenericApplicationContext context, + MergedContextConfiguration mergedContextConfiguration) { + createBeanDefinitionReader(context).loadBeanDefinitions(mergedContextConfiguration.getLocations()); } /** @@ -167,7 +163,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader * loading bean definitions into the supplied {@link GenericApplicationContext context}. * @param context the context for which the BeanDefinitionReader should be created * @return a BeanDefinitionReader for the supplied context - * @see #loadBeanDefinitions + * @see #loadContext(String...) * @see BeanDefinitionReader */ protected abstract BeanDefinitionReader createBeanDefinitionReader(GenericApplicationContext context); diff --git a/org.springframework.test/src/main/java/org/springframework/test/context/support/AnnotationConfigContextLoader.java b/org.springframework.test/src/main/java/org/springframework/test/context/support/AnnotationConfigContextLoader.java index 5a166357593..e8aaac12797 100644 --- a/org.springframework.test/src/main/java/org/springframework/test/context/support/AnnotationConfigContextLoader.java +++ b/org.springframework.test/src/main/java/org/springframework/test/context/support/AnnotationConfigContextLoader.java @@ -16,12 +16,16 @@ package org.springframework.test.context.support; +import java.util.ArrayList; +import java.util.List; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.support.BeanDefinitionReader; import org.springframework.context.annotation.AnnotatedBeanDefinitionReader; import org.springframework.context.support.GenericApplicationContext; -import org.springframework.test.context.ContextLoader; +import org.springframework.test.context.ContextConfigurationAttributes; +import org.springframework.test.context.MergedContextConfiguration; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -30,13 +34,6 @@ import org.springframework.util.ObjectUtils; * registers bean definitions from * {@link org.springframework.context.annotation.Configuration configuration classes}. * - *

    This ContextLoader supports class-based context configuration - * {@link #getResourceType() resources} as opposed to string-based resources. - * Consequently, locations (as discussed in the {@link ContextLoader} - * API and superclasses) are interpreted as fully qualified class names - * in the context of this class. The documentation and method parameters - * reflect this. - * * @author Sam Brannen * @since 3.1 */ @@ -46,6 +43,21 @@ public class AnnotationConfigContextLoader extends AbstractGenericContextLoader /** + * TODO Document overridden processContextConfigurationAttributes(). + * + * @see org.springframework.test.context.SmartContextLoader#processContextConfigurationAttributes + */ + public void processContextConfigurationAttributes(ContextConfigurationAttributes configAttributes) { + if (ObjectUtils.isEmpty(configAttributes.getClasses()) && isGenerateDefaultClasses()) { + Class[] defaultConfigurationClasses = generateDefaultConfigurationClasses(configAttributes.getDeclaringClass()); + configAttributes.setClasses(defaultConfigurationClasses); + } + } + + /** + * TODO Update documentation regarding SmartContextLoader SPI. + * + *

    * Registers {@link org.springframework.context.annotation.Configuration configuration classes} * in the supplied {@link GenericApplicationContext context} from the specified * class names. @@ -64,21 +76,9 @@ public class AnnotationConfigContextLoader extends AbstractGenericContextLoader * @throws IllegalArgumentException if a supplied class name does not represent a class */ @Override - protected void loadBeanDefinitions(GenericApplicationContext context, String... classNames) { - - Class[] configClasses = new Class[classNames.length]; - - for (int i = 0; i < classNames.length; i++) { - String className = classNames[i]; - try { - configClasses[i] = (Class) context.getClassLoader().loadClass(className); - } - catch (ClassNotFoundException e) { - throw new IllegalArgumentException(String.format( - "The supplied class name [%s] does not represent a class.", className), e); - } - } - + protected void loadBeanDefinitions(GenericApplicationContext context, + MergedContextConfiguration mergedContextConfiguration) { + Class[] configClasses = mergedContextConfiguration.getClasses(); if (logger.isDebugEnabled()) { logger.debug("Registering configuration classes: " + ObjectUtils.nullSafeToString(configClasses)); } @@ -86,40 +86,10 @@ public class AnnotationConfigContextLoader extends AbstractGenericContextLoader } /** - * Returns null; intended as a no-op operation. + * TODO Document isGenerateDefaultClasses(). */ - @Override - protected BeanDefinitionReader createBeanDefinitionReader(GenericApplicationContext context) { - return null; - } - - /** - * Generates the default {@link org.springframework.context.annotation.Configuration configuration class} - * names array based on the supplied class. - * - *

    For example, if the supplied class is com.example.MyTest, - * the generated array will contain a single string with a value of - * "com.example.MyTest<suffix>", - * where <suffix> is the value of the - * {@link #getResourceSuffix() resource suffix} string. - * @param clazz the class for which the default configuration class names are to be generated - * @return an array of default configuration class names - * @see #getResourceSuffix() - */ - @Override - protected String[] generateDefaultLocations(Class clazz) { - Assert.notNull(clazz, "Class must not be null"); - String suffix = getResourceSuffix(); - Assert.hasText(suffix, "Resource suffix must not be empty"); - return new String[] { clazz.getName() + suffix }; - } - - /** - * Returns the supplied class names unmodified. - */ - @Override - protected String[] modifyLocations(Class clazz, String... classNames) { - return classNames; + protected boolean isGenerateDefaultClasses() { + return true; } /** @@ -133,17 +103,64 @@ public class AnnotationConfigContextLoader extends AbstractGenericContextLoader * * @see #generateDefaultLocations(Class) */ - @Override - protected String getResourceSuffix() { + protected String getConfigurationClassNameSuffix() { return "$ContextConfiguration"; } /** - * Returns {@link ResourceType#CLASSES}. + * TODO Document generateDefaultConfigurationClasses(). + */ + protected Class[] generateDefaultConfigurationClasses(Class declaringClass) { + Assert.notNull(declaringClass, "Declaring class must not be null"); + String suffix = getConfigurationClassNameSuffix(); + Assert.hasText(suffix, "Configuration class name suffix must not be empty"); + String className = declaringClass.getName() + suffix; + + List> configClasses = new ArrayList>(); + try { + configClasses.add((Class) getClass().getClassLoader().loadClass(className)); + } + catch (ClassNotFoundException e) { + logger.warn(String.format("Cannot load @Configuration class with generated class name [%s].", className), e); + } + + return configClasses.toArray(new Class[configClasses.size()]); + } + + /** + * TODO Document overridden createBeanDefinitionReader(). */ @Override - public final ResourceType getResourceType() { - return ResourceType.CLASSES; + protected BeanDefinitionReader createBeanDefinitionReader(GenericApplicationContext context) { + throw new UnsupportedOperationException( + "AnnotationConfigContextLoader does not support the createBeanDefinitionReader(GenericApplicationContext) method"); + } + + /** + * TODO Document overridden generateDefaultLocations(). + */ + @Override + protected String[] generateDefaultLocations(Class clazz) { + throw new UnsupportedOperationException( + "AnnotationConfigContextLoader does not support the generateDefaultLocations(Class) method"); + } + + /** + * TODO Document overridden modifyLocations(). + */ + @Override + protected String[] modifyLocations(Class clazz, String... locations) { + throw new UnsupportedOperationException( + "AnnotationConfigContextLoader does not support the modifyLocations(Class, String...) method"); + } + + /** + * TODO Document overridden getResourceSuffix(). + */ + @Override + protected String getResourceSuffix() { + throw new UnsupportedOperationException( + "AnnotationConfigContextLoader does not support the getResourceSuffix() method"); } } diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/ContextLoaderUtilsTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/ContextLoaderUtilsTests.java index 7a32edb9ae1..8f1df7e3fc5 100644 --- a/org.springframework.test/src/test/java/org/springframework/test/context/ContextLoaderUtilsTests.java +++ b/org.springframework.test/src/test/java/org/springframework/test/context/ContextLoaderUtilsTests.java @@ -38,6 +38,7 @@ import org.springframework.test.context.support.GenericXmlContextLoader; */ public class ContextLoaderUtilsTests { + private static final Class[] EMPTY_CLASS_ARRAY = new Class[] {}; private static final String[] EMPTY_STRING_ARRAY = new String[] {}; @@ -48,7 +49,7 @@ public class ContextLoaderUtilsTests { assertArrayEquals(expectedLocations, attributes.getLocations()); assertArrayEquals(expectedClasses, attributes.getClasses()); assertEquals(expectedInheritLocations, attributes.isInheritLocations()); - assertEquals(expectedContextLoaderClass, attributes.getContextLoader()); + assertEquals(expectedContextLoaderClass, attributes.getContextLoaderClass()); } private void assertFooAttributes(ContextConfigurationAttributes attributes) { @@ -62,12 +63,14 @@ public class ContextLoaderUtilsTests { } private void assertMergedContextConfiguration(MergedContextConfiguration mergedConfig, Class expectedTestClass, - String[] expectedLocations, Class expectedContextLoaderClass) { + String[] expectedLocations, Class[] expectedClasses, + Class expectedContextLoaderClass) { assertNotNull(mergedConfig); assertEquals(expectedTestClass, mergedConfig.getTestClass()); assertNotNull(mergedConfig.getLocations()); assertArrayEquals(expectedLocations, mergedConfig.getLocations()); assertNotNull(mergedConfig.getClasses()); + assertArrayEquals(expectedClasses, mergedConfig.getClasses()); assertNotNull(mergedConfig.getActiveProfiles()); assertEquals(expectedContextLoaderClass, mergedConfig.getContextLoader().getClass()); } @@ -82,7 +85,7 @@ public class ContextLoaderUtilsTests { List attributesList = ContextLoaderUtils.resolveContextConfigurationAttributes(BareAnnotations.class); assertNotNull(attributesList); assertEquals(1, attributesList.size()); - assertAttributes(attributesList.get(0), BareAnnotations.class, EMPTY_STRING_ARRAY, new Class[] {}, + assertAttributes(attributesList.get(0), BareAnnotations.class, EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, ContextLoader.class, true); } @@ -117,7 +120,7 @@ public class ContextLoaderUtilsTests { mergedConfig, testClass, new String[] { "classpath:/org/springframework/test/context/ContextLoaderUtilsTests$BareAnnotations-context.xml" }, - GenericXmlContextLoader.class); + EMPTY_CLASS_ARRAY, GenericXmlContextLoader.class); } @Test @@ -126,31 +129,28 @@ public class ContextLoaderUtilsTests { MergedContextConfiguration mergedConfig = ContextLoaderUtils.buildMergedContextConfiguration(testClass, null); assertMergedContextConfiguration(mergedConfig, testClass, new String[] { "classpath:/foo.xml" }, - GenericXmlContextLoader.class); + new Class[] { FooConfig.class }, GenericXmlContextLoader.class); } @Test - public void buildMergedContextConfigurationWithLocalAnnotationAndOverriddenContexLoader() { + public void buildMergedContextConfigurationWithLocalAnnotationAndOverriddenContextLoader() { Class testClass = Foo.class; Class expectedContextLoaderClass = GenericPropertiesContextLoader.class; MergedContextConfiguration mergedConfig = ContextLoaderUtils.buildMergedContextConfiguration(testClass, expectedContextLoaderClass.getName()); assertMergedContextConfiguration(mergedConfig, testClass, new String[] { "classpath:/foo.xml" }, - expectedContextLoaderClass); + new Class[] { FooConfig.class }, expectedContextLoaderClass); } @Test public void buildMergedContextConfigurationWithLocalAndInheritedAnnotations() { Class testClass = Bar.class; + String[] expectedLocations = new String[] { "/foo.xml", "/bar.xml" }; + Class[] expectedClasses = new Class[] { FooConfig.class, BarConfig.class }; + MergedContextConfiguration mergedConfig = ContextLoaderUtils.buildMergedContextConfiguration(testClass, null); - - // TODO Assert @Configuration classes instead of locations - String[] expectedLocations = new String[] { - "org.springframework.test.context.ContextLoaderUtilsTests$FooConfig", - "org.springframework.test.context.ContextLoaderUtilsTests$BarConfig" }; - - assertMergedContextConfiguration(mergedConfig, testClass, expectedLocations, + assertMergedContextConfiguration(mergedConfig, testClass, expectedLocations, expectedClasses, AnnotationConfigContextLoader.class); } diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/TestContextCacheKeyTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/TestContextCacheKeyTests.java index 41c0d9a3035..c8a21e32b6d 100644 --- a/org.springframework.test/src/test/java/org/springframework/test/context/TestContextCacheKeyTests.java +++ b/org.springframework.test/src/test/java/org/springframework/test/context/TestContextCacheKeyTests.java @@ -27,7 +27,7 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader; /** * Unit tests for verifying proper behavior of the {@link ContextCache} in - * conjunction with cache keys generated in {@link TestContext}. + * conjunction with cache keys used in {@link TestContext}. * * @author Sam Brannen * @since 3.1 diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java index 573ede18d92..40a89205730 100644 --- a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java +++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,8 +22,11 @@ import org.junit.runners.Suite.SuiteClasses; import org.springframework.test.context.ClassLevelDirtiesContextTests; import org.springframework.test.context.SpringRunnerContextCacheTests; import org.springframework.test.context.junit4.annotation.AnnotationConfigSpringJUnit4ClassRunnerAppCtxTests; +import org.springframework.test.context.junit4.annotation.BeanOverridingDefaultConfigClassesInheritedTests; +import org.springframework.test.context.junit4.annotation.BeanOverridingExplicitConfigClassesInheritedTests; import org.springframework.test.context.junit4.annotation.DefaultConfigClassesBaseTests; import org.springframework.test.context.junit4.annotation.DefaultConfigClassesInheritedTests; +import org.springframework.test.context.junit4.annotation.ExplicitConfigClassesInheritedTests; import org.springframework.test.context.junit4.orm.HibernateSessionFlushingTests; import org.springframework.test.context.junit4.profile.annotation.DefaultProfileAnnotationConfigTests; import org.springframework.test.context.junit4.profile.annotation.DevProfileAnnotationConfigTests; @@ -31,20 +34,16 @@ import org.springframework.test.context.junit4.profile.xml.DefaultProfileXmlConf import org.springframework.test.context.junit4.profile.xml.DevProfileXmlConfigTests; /** - *

    - * JUnit 4 based test suite for tests involving {@link SpringJUnit4ClassRunner} - * and the Spring TestContext Framework. - *

    - *

    - * This test suite serves a dual purpose of verifying that tests run with - * {@link SpringJUnit4ClassRunner} can be used in conjunction with JUnit 4's + * JUnit test suite for tests involving {@link SpringJUnit4ClassRunner} and the + * Spring TestContext Framework. + * + *

    This test suite serves a dual purpose of verifying that tests run with + * {@link SpringJUnit4ClassRunner} can be used in conjunction with JUnit's * {@link Suite} runner. - *

    - *

    - * Note that tests included in this suite will be executed at least twice if run - * from an automated build process, test runner, etc. that is configured to run - * tests based on a "*Tests.class" pattern match. - *

    + * + *

    Note that tests included in this suite will be executed at least twice if + * run from an automated build process, test runner, etc. that is configured to + * run tests based on a "*Tests.class" pattern match. * * @author Sam Brannen * @since 2.5 @@ -58,6 +57,9 @@ StandardJUnit4FeaturesTests.class,// AnnotationConfigSpringJUnit4ClassRunnerAppCtxTests.class,// DefaultConfigClassesBaseTests.class,// DefaultConfigClassesInheritedTests.class,// + BeanOverridingDefaultConfigClassesInheritedTests.class,// + ExplicitConfigClassesInheritedTests.class,// + BeanOverridingExplicitConfigClassesInheritedTests.class,// DefaultProfileAnnotationConfigTests.class,// DevProfileAnnotationConfigTests.class, // DefaultProfileXmlConfigTests.class,//