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 436fba4955..b089366738 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 @@ -22,11 +22,15 @@ import org.springframework.core.style.ToStringCreator; import org.springframework.util.ObjectUtils; /** - * TODO [SPR-8386] Document ContextConfigurationAttributes. + * ContextConfigurationAttributes encapsulates the context + * configuration attributes declared on a test class via + * {@link ContextConfiguration @ContextConfiguration}. * * @author Sam Brannen * @since 3.1 * @see ContextConfiguration + * @see SmartContextLoader + * @see MergedContextConfiguration */ public class ContextConfigurationAttributes { @@ -34,17 +38,17 @@ public class ContextConfigurationAttributes { private final Class declaringClass; - private final boolean inheritLocations; - - private final Class contextLoaderClass; - private String[] locations; private Class[] classes; + private final boolean inheritLocations; + + private final Class contextLoaderClass; + /** - * Resolves resource locations from the {@link ContextConfiguration#locations() locations} + * Resolve resource locations from the {@link ContextConfiguration#locations() locations} * and {@link ContextConfiguration#value() value} attributes of the supplied * {@link ContextConfiguration} annotation. * @@ -71,7 +75,11 @@ public class ContextConfigurationAttributes { } /** - * TODO Document ContextConfigurationAttributes constructor. + * Construct a new {@link ContextConfigurationAttributes} instance for the + * supplied {@link ContextConfiguration @ContextConfiguration} annotation and + * the {@link Class test class} that declared it. + * @param declaringClass the test class that declared {@code @ContextConfiguration} + * @param contextConfiguration the annotation from which to retrieve the attributes */ public ContextConfigurationAttributes(Class declaringClass, ContextConfiguration contextConfiguration) { this(declaringClass, resolveLocations(declaringClass, contextConfiguration), contextConfiguration.classes(), @@ -79,7 +87,16 @@ public class ContextConfigurationAttributes { } /** - * TODO Document ContextConfigurationAttributes constructor. + * Construct a new {@link ContextConfigurationAttributes} instance for the + * {@link Class test class} that declared the + * {@link ContextConfiguration @ContextConfiguration} annotation and its + * corresponding attributes. + * + * @param declaringClass the test class that declared {@code @ContextConfiguration} + * @param locations the resource locations declared via {@code @ContextConfiguration} + * @param classes the configuration classes declared via {@code @ContextConfiguration} + * @param inheritLocations the inheritLocations flag declared via {@code @ContextConfiguration} + * @param contextLoaderClass the {@code ContextLoader} class declared via {@code @ContextConfiguration} */ public ContextConfigurationAttributes(Class declaringClass, String[] locations, Class[] classes, boolean inheritLocations, Class contextLoaderClass) { @@ -91,56 +108,84 @@ public class ContextConfigurationAttributes { } /** - * TODO Document getDeclaringClass(). + * Get the {@link Class class} that declared the + * {@link ContextConfiguration @ContextConfiguration} annotation. + * @return the declaring class; never null */ public Class getDeclaringClass() { return this.declaringClass; } /** - * TODO Document isInheritLocations(). - */ - public boolean isInheritLocations() { - return this.inheritLocations; - } - - /** - * TODO Document getContextLoaderClass(). - */ - public Class getContextLoaderClass() { - return this.contextLoaderClass; - } - - /** - * TODO Document getLocations(). + * Get the resource locations that were declared via + * {@link ContextConfiguration @ContextConfiguration}. + *

Note: this is a mutable property. The returned value may therefore + * represent a processed value that does not match the original value + * declared via {@link ContextConfiguration @ContextConfiguration}. + * @return the resource locations; potentially null or empty + * @see ContextConfiguration#value + * @see ContextConfiguration#locations + * @see #setLocations() */ public String[] getLocations() { return this.locations; } /** - * TODO Document setLocations(). + * Set the processed resource locations, effectively overriding the + * original value declared via {@link ContextConfiguration @ContextConfiguration}. + * @see #getLocations() */ public void setLocations(String[] locations) { this.locations = locations; } /** - * TODO Document getClasses(). + * Get the configuration classes that were declared via + * {@link ContextConfiguration @ContextConfiguration}. + *

Note: this is a mutable property. The returned value may therefore + * represent a processed value that does not match the original value + * declared via {@link ContextConfiguration @ContextConfiguration}. + * @return the configuration classes; potentially null or empty + * @see ContextConfiguration#classes + * @see #setClasses() */ public Class[] getClasses() { return this.classes; } /** - * TODO Document setClasses(). + * Set the processed configuration classes, effectively overriding the + * original value declared via {@link ContextConfiguration @ContextConfiguration}. + * @see #getClasses() */ public void setClasses(Class[] classes) { this.classes = classes; } /** - * TODO Document overridden toString(). + * Get the inheritLocations flag that was declared via + * {@link ContextConfiguration @ContextConfiguration}. + * @return the inheritLocations flag + * @see ContextConfiguration#inheritLocations + */ + public boolean isInheritLocations() { + return this.inheritLocations; + } + + /** + * Get the ContextLoader class that was declared via + * {@link ContextConfiguration @ContextConfiguration}. + * @return the ContextLoader class + * @see ContextConfiguration#loader + */ + public Class getContextLoaderClass() { + return this.contextLoaderClass; + } + + /** + * Provide a String representation of the context configuration attributes + * and declaring class. */ @Override public String toString() { diff --git a/org.springframework.test/src/main/java/org/springframework/test/context/ContextLoader.java b/org.springframework.test/src/main/java/org/springframework/test/context/ContextLoader.java index b0c2a4e404..1477291a77 100644 --- a/org.springframework.test/src/main/java/org/springframework/test/context/ContextLoader.java +++ b/org.springframework.test/src/main/java/org/springframework/test/context/ContextLoader.java @@ -20,6 +20,10 @@ import org.springframework.context.ApplicationContext; /** * Strategy interface for loading an {@link ApplicationContext application context}. + * + *

Note: as of Spring 3.1, consider implementing {@link SmartContextLoader} + * instead of this interface in order to provide support for configuration classes + * and active bean definition profiles. * *

Clients of a ContextLoader should call * {@link #processLocations(Class,String...) processLocations()} prior to @@ -41,6 +45,7 @@ import org.springframework.context.ApplicationContext; * @author Sam Brannen * @author Juergen Hoeller * @since 2.5 + * @see SmartContextLoader */ public interface ContextLoader { 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 c3e3856d7d..1601ff921d 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 @@ -100,7 +100,7 @@ abstract class ContextLoaderUtils { * * @param testClass the test class for which the ContextLoader * should be resolved (must not be null) - * @param configAttributesList TODO Document parameter + * @param configAttributesList TODO Document configAttributesList parameter * @param defaultContextLoaderClassName the name of the default * ContextLoader class to use (may be null) * @@ -141,7 +141,7 @@ abstract class ContextLoaderUtils { * * @param testClass the class for which to resolve the ContextLoader * class; must not be null - * @param configAttributesList TODO Document parameter + * @param configAttributesList TODO Document configAttributesList parameter * @param defaultContextLoaderClassName the name of the default * ContextLoader class to use; must not be null or empty * 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 b9fc50fc36..05e94fe7bb 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 @@ -31,6 +31,7 @@ import org.springframework.util.StringUtils; * @since 3.1 * @see ContextConfiguration * @see ActiveProfiles + * @see ContextConfigurationAttributes */ public class MergedContextConfiguration { 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 e9c19b64bb..292def6f86 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 @@ -19,20 +19,111 @@ package org.springframework.test.context; import org.springframework.context.ApplicationContext; /** - * TODO [SPR-8386] Document SmartContextLoader. + *

Strategy interface for loading an {@link ApplicationContext application context} + * for an integration test managed by the Spring TestContext Framework. + * + *

The SmartContextLoader SPI supersedes the {@link ContextLoader} + * SPI introduced in Spring 2.5: SmartContextLoaders can process both + * resource locations and configuration classes. Furthermore, a + * SmartContextLoader can set active bean definition profiles + * in the context that it loads (see {@link MergedContextConfiguration#getActiveProfiles()} + * and {@link #loadContext(MergedContextConfiguration)}). + * + *

Clients of a SmartContextLoader should call + * {@link #processContextConfiguration(ContextConfigurationAttributes) processContextConfiguration()} + * prior to calling {@link #loadContext(MergedContextConfiguration) loadContext()} + * in case the SmartContextLoader provides custom support for modifying + * or generating resource locations or configuration classes. The results of + * {@link #processContextConfiguration(ContextConfigurationAttributes) processContextConfiguration()} + * should be merged for all classes in the hierarchy of the root test class and + * then supplied to {@link #loadContext(MergedContextConfiguration) loadContext()}. + * Even though SmartContextLoader extends ContextLoader, + * clients should favor SmartContextLoader-specific methods over those + * defined in ContextLoader, particularly because a + * SmartContextLoader may choose not to support methods defined in + * the ContextLoader SPI. + * + *

Concrete implementations must provide a public no-args constructor. + * + *

Spring provides the following out-of-the-box implementations: + *

* * @author Sam Brannen * @since 3.1 + * @see ContextConfiguration + * @see ActiveProfiles + * @see ContextConfigurationAttributes + * @see MergedContextConfiguration */ public interface SmartContextLoader extends ContextLoader { /** - * TODO Document processContextConfiguration(). + * Determines if this SmartContextLoader generates default resource + * locations or + * {@link org.springframework.context.annotation.Configuration configuration classes} + * if the locations or classes + * present in the {@link ContextConfigurationAttributes} provided to + * {@link #processContextConfiguration()} are null or empty. + *

Returning a value of true signals not only that this + * SmartContextLoader generates defaults but also that it will + * preemptively verify that a generated default actually exists. + * @return true if this SmartContextLoader + * generates default configuration locations or classes + * @see #processContextConfiguration + */ + boolean generatesDefaults(); + + /** + * Processes the {@link ContextConfigurationAttributes} for a given test class. + *

Concrete implementations may choose to modify the locations + * or classes in the supplied {@link ContextConfigurationAttributes} + * or generate default configuration locations or classes if the + * supplied values are null or empty. + *

Note: If {@link #generatesDefaults()} returns true, + * this method must preemptively verify that a generated default + * actually exists before setting the corresponding locations + * or classes property in the supplied + * {@link ContextConfigurationAttributes}. Consequently, leaving the + * locations or classes property empty signals that + * this SmartContextLoader was not able to generate defaults. + * @param configAttributes the context configuration attributes to process + * @see #generatesDefaults */ void processContextConfiguration(ContextConfigurationAttributes configAttributes); /** - * TODO Document loadContext(). + * Loads a new {@link ApplicationContext context} based on the supplied + * {@link MergedContextConfiguration merged context configuration}, + * configures the context, and finally returns the context in a fully + * refreshed state. + *

Concrete implementations should register annotation configuration + * processors with bean factories of + * {@link ApplicationContext application contexts} loaded by this + * SmartContextLoader. Beans will therefore automatically be + * candidates for annotation-based dependency injection using + * {@link org.springframework.beans.factory.annotation.Autowired @Autowired}, + * {@link javax.annotation.Resource @Resource}, and + * {@link javax.inject.Inject @Inject}. In addition, concrete implementations + * should set the active bean definition profiles in the context's + * {@link org.springframework.core.env.Environment Environment}. + *

Any ApplicationContext loaded by a + * SmartContextLoader must register a JVM + * shutdown hook for itself. Unless the context gets closed early, all context + * instances will be automatically closed on JVM shutdown. This allows for + * freeing external resources held by beans within the context (e.g., + * temporary files). + * @param mergedConfig the merged context configuration to use to load the + * application context + * @return a new application context + * @throws Exception if context loading failed + * @see #processContextConfiguration(ContextConfigurationAttributes) + * @see org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors() + * @see org.springframework.test.context.MergedContextConfiguration#getActiveProfiles() + * @see org.springframework.context.ConfigurableApplicationContext#getEnvironment() */ ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception; 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 a43ce9a2b5..10bdd55626 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 @@ -41,6 +41,22 @@ import org.springframework.util.StringUtils; */ public abstract class AbstractContextLoader implements SmartContextLoader { + // --- SmartContextLoader ----------------------------------------------- + + /** + * Determine whether or not default resource locations should be + * generated if the locations provided to + * {@link #processLocations(Class,String...) processLocations()} are + * null or empty. + *

Can be overridden by subclasses to change the default behavior. + * @return always true by default + * + * @see SmartContextLoader#generatesDefaults + */ + public boolean generatesDefaults() { + return isGenerateDefaultLocations(); + } + /** * TODO Document processContextConfiguration(). */ @@ -51,6 +67,8 @@ public abstract class AbstractContextLoader implements SmartContextLoader { configAttributes.setLocations(processedLocations); } + // --- ContextLoader ------------------------------------------------------- + /** * If the supplied locations are null or * empty and {@link #isGenerateDefaultLocations()} is 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 56aa7a1438..d000b4f921 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 @@ -101,14 +101,6 @@ public class AnnotationConfigContextLoader extends AbstractGenericContextLoader return clazz != null && isStaticNonPrivateAndNonFinal(clazz) && clazz.isAnnotationPresent(Configuration.class); } - /** - * TODO Document generatesDefaults(). - */ - // TODO Consider defining generatesDefaults() in the SmartContextLoader SPI. - protected boolean generatesDefaults() { - return true; - } - /** * TODO Document generateDefaultConfigurationClasses(). */ diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/xml/DefaultProfileXmlConfigTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/xml/DefaultProfileXmlConfigTests.java index 30ebb271cb..f79a9b0aa5 100644 --- a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/xml/DefaultProfileXmlConfigTests.java +++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/xml/DefaultProfileXmlConfigTests.java @@ -29,8 +29,6 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** - * TODO Document DefaultProfileXmlConfigTests. - * * @author Sam Brannen * @since 3.1 */ diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/xml/DevProfileXmlConfigTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/xml/DevProfileXmlConfigTests.java index ebe65b1792..43d6a5a7b4 100644 --- a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/xml/DevProfileXmlConfigTests.java +++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/xml/DevProfileXmlConfigTests.java @@ -23,8 +23,6 @@ import org.junit.Test; import org.springframework.test.context.ActiveProfiles; /** - * TODO Document DefaultProfileXmlConfigTests. - * * @author Sam Brannen * @since 3.1 */