Document WebApplicationContext support in the TCF

This commit adds Javadoc documentation for the WebApplicationContext
testing support that was recently introduced in the Spring TestContext
Framework.

Issue: SPR-9864
This commit is contained in:
Sam Brannen 2012-12-11 01:58:10 +01:00
parent c8a3562933
commit a6387dc725
7 changed files with 236 additions and 37 deletions

View File

@ -23,10 +23,12 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.SmartContextLoader;
import org.springframework.util.Assert;
/**
* TODO [SPR-9864] Document AnnotationConfigContextLoaderUtils.
* Utility methods for {@link SmartContextLoader SmartContextLoaders} that deal
* with annotated classes (e.g., {@link Configuration @Configuration} classes).
*
* @author Sam Brannen
* @since 3.2

View File

@ -20,6 +20,7 @@ import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
@ -34,10 +35,26 @@ import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.GenericWebApplicationContext;
/**
* TODO [SPR-9864] Document AbstractGenericWebContextLoader.
* Abstract, generic extension of {@link AbstractContextLoader} that loads a
* {@link GenericWebApplicationContext}.
*
* <p>If instances of concrete subclasses are invoked via the
* {@link org.springframework.test.context.SmartContextLoader SmartContextLoader}
* SPI, the context will be loaded from the {@link MergedContextConfiguration}
* provided to {@link #loadContext(MergedContextConfiguration)}. In such cases, a
* {@code SmartContextLoader} will decide whether to load the context from
* <em>locations</em> or <em>annotated classes</em>. Note that {@code
* AbstractGenericWebContextLoader} does not support the {@code
* loadContext(String... locations)} method from the legacy
* {@link org.springframework.test.context.ContextLoader ContextLoader} SPI.
*
* <p>Concrete subclasses must provide an appropriate implementation of
* {@link #loadBeanDefinitions()}.
*
* @author Sam Brannen
* @since 3.2
* @see #loadContext(MergedContextConfiguration)
* @see #loadContext(String...)
*/
public abstract class AbstractGenericWebContextLoader extends AbstractContextLoader {
@ -47,9 +64,33 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
// --- SmartContextLoader -----------------------------------------------
/**
* TODO [SPR-9864] Document overridden loadContext(MergedContextConfiguration).
* Load a Spring {@link WebApplicationContext} from the supplied
* {@link MergedContextConfiguration}.
*
* @see org.springframework.test.context.SmartContextLoader#loadContext(org.springframework.test.context.MergedContextConfiguration)
* <p>Implementation details:
*
* <ul>
* <li>Creates a {@link GenericWebApplicationContext} instance.</li>
* <li>Delegates to {@link #configureWebResources()} to create the
* {@link MockServletContext} and set it in the {@code WebApplicationContext}.</li>
* <li>Calls {@link #prepareContext()} to allow for customizing the context
* before bean definitions are loaded.</li>
* <li>Calls {@link #customizeBeanFactory()} to allow for customizing the
* context's {@code DefaultListableBeanFactory}.</li>
* <li>Delegates to {@link #loadBeanDefinitions()} to populate the context
* from the locations or classes in the supplied {@code MergedContextConfiguration}.</li>
* <li>Delegates to {@link AnnotationConfigUtils} for
* {@linkplain AnnotationConfigUtils#registerAnnotationConfigProcessors registering}
* annotation configuration processors.</li>
* <li>Calls {@link #customizeContext()} to allow for customizing the context
* before it is refreshed.</li>
* <li>{@link ConfigurableApplicationContext#refresh Refreshes} the
* context and registers a JVM shutdown hook for it.</li>
* </ul>
*
* @return a new web application context
* @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration)
* @see GenericWebApplicationContext
*/
public final ConfigurableApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
@ -78,7 +119,29 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
}
/**
* TODO [SPR-9864] Document configureWebResources().
* Configures web resources for the supplied web application context.
*
* <p>Implementation details:
*
* <ul>
* <li>The resource base path is retrieved from the supplied
* {@code WebMergedContextConfiguration}.</li>
* <li>A {@link ResourceLoader} is instantiated for the {@link MockServletContext}:
* if the resource base path is prefixed with "{@code classpath:}", a
* {@link DefaultResourceLoader} will be used; otherwise, a
* {@link FileSystemResourceLoader} will be used.</li>
* <li>A {@code MockServletContext} will be created using the resource base
* path and resource loader.</li>
* <li>The supplied {@link GenericWebApplicationContext} is then stored in
* the {@code MockServletContext} under the
* {@link WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE} key.</li>
* <li>Finally, the {@code MockServletContext} is set in the
* {@code WebApplicationContext}.</li>
*
* @param context the web application context for which to configure the web
* resources
* @param webMergedConfig the merged context configuration to use to load the
* web application context
*/
protected void configureWebResources(GenericWebApplicationContext context,
WebMergedContextConfiguration webMergedConfig) {
@ -93,20 +156,51 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
}
/**
* TODO [SPR-9864] Document customizeBeanFactory().
* Customize the internal bean factory of the {@code WebApplicationContext}
* created by this context loader.
*
* <p>The default implementation is empty but can be overridden in subclasses
* to customize <code>DefaultListableBeanFactory</code>'s standard settings.
*
* @param beanFactory the bean factory created by this context loader
* @param webMergedConfig the merged context configuration to use to load the
* web application context
* @see #loadContext(MergedContextConfiguration)
* @see DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
* @see DefaultListableBeanFactory#setAllowEagerClassLoading
* @see DefaultListableBeanFactory#setAllowCircularReferences
* @see DefaultListableBeanFactory#setAllowRawInjectionDespiteWrapping
*/
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory,
WebMergedContextConfiguration webMergedConfig) {
}
/**
* TODO [SPR-9864] Document loadBeanDefinitions().
* Load bean definitions into the supplied {@link GenericWebApplicationContext context}
* from the locations or classes in the supplied <code>WebMergedContextConfiguration</code>.
*
* <p>Concrete subclasses must provide an appropriate implementation.
*
* @param context the context into which the bean definitions should be loaded
* @param webMergedConfig the merged context configuration to use to load the
* web application context
* @see #loadContext(MergedContextConfiguration)
*/
protected abstract void loadBeanDefinitions(GenericWebApplicationContext context,
WebMergedContextConfiguration webMergedConfig);
/**
* TODO [SPR-9864] Document customizeContext().
* Customize the {@link GenericWebApplicationContext} created by this context
* loader <i>after</i> bean definitions have been loaded into the context but
* <i>before</i> the context is refreshed.
*
* <p>The default implementation is empty but can be overridden in subclasses
* to customize the web application context.
*
* @param context the newly created web application context
* @param webMergedConfig the merged context configuration to use to load the
* web application context
* @see #loadContext(MergedContextConfiguration)
*/
protected void customizeContext(GenericWebApplicationContext context, WebMergedContextConfiguration webMergedConfig) {
}
@ -114,9 +208,13 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
// --- ContextLoader -------------------------------------------------------
/**
* TODO [SPR-9864] Document overridden loadContext(String...).
* {@code AbstractGenericWebContextLoader} should be used as a
* {@link org.springframework.test.context.SmartContextLoader SmartContextLoader},
* not as a legacy {@link org.springframework.test.context.ContextLoader ContextLoader}.
* Consequently, this method is not supported.
*
* @see org.springframework.test.context.ContextLoader#loadContext(java.lang.String[])
* @throws UnsupportedOperationException
*/
public final ApplicationContext loadContext(String... locations) throws Exception {
throw new UnsupportedOperationException(

View File

@ -18,18 +18,38 @@ package org.springframework.test.context.web;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.support.AbstractContextLoader;
import org.springframework.test.context.support.AnnotationConfigContextLoaderUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.support.GenericWebApplicationContext;
/**
* TODO [SPR-9864] Document AnnotationConfigWebContextLoader.
* Concrete implementation of {@link AbstractGenericWebContextLoader} that loads
* bean definitions from annotated classes.
*
* <p>See the Javadoc for
* {@link org.springframework.test.context.ContextConfiguration @ContextConfiguration}
* for a definition of <em>annotated class</em>.
*
* <p>Note: <code>AnnotationConfigWebContextLoader</code> supports <em>annotated classes</em>
* rather than the String-based resource locations defined by the legacy
* {@link org.springframework.test.context.ContextLoader ContextLoader} API. Thus,
* although <code>AnnotationConfigWebContextLoader</code> extends
* <code>AbstractGenericWebContextLoader</code>, <code>AnnotationConfigWebContextLoader</code>
* does <em>not</em> support any String-based methods defined by
* {@link org.springframework.test.context.support.AbstractContextLoader
* AbstractContextLoader} or <code>AbstractGenericWebContextLoader</code>.
* Consequently, <code>AnnotationConfigWebContextLoader</code> should chiefly be
* considered a {@link org.springframework.test.context.SmartContextLoader SmartContextLoader}
* rather than a {@link org.springframework.test.context.ContextLoader ContextLoader}.
*
* @author Sam Brannen
* @since 3.2
* @see #processContextConfiguration(ContextConfigurationAttributes)
* @see #detectDefaultConfigurationClasses(Class)
* @see #loadBeanDefinitions(GenericWebApplicationContext, WebMergedContextConfiguration)
*/
public class AnnotationConfigWebContextLoader extends AbstractGenericWebContextLoader {
@ -43,10 +63,10 @@ public class AnnotationConfigWebContextLoader extends AbstractGenericWebContextL
*
* <p>If the <em>annotated classes</em> are <code>null</code> or empty and
* {@link #isGenerateDefaultLocations()} returns <code>true</code>, this
* <code>SmartContextLoader</code> will attempt to {@link
* <code>SmartContextLoader</code> will attempt to {@linkplain
* #detectDefaultConfigurationClasses detect default configuration classes}.
* If defaults are detected they will be
* {@link ContextConfigurationAttributes#setClasses(Class[]) set} in the
* {@linkplain ContextConfigurationAttributes#setClasses(Class[]) set} in the
* supplied configuration attributes. Otherwise, properties in the supplied
* configuration attributes will not be modified.
*
@ -85,7 +105,7 @@ public class AnnotationConfigWebContextLoader extends AbstractGenericWebContextL
* not as a legacy {@link org.springframework.test.context.ContextLoader ContextLoader}.
* Consequently, this method is not supported.
*
* @see AbstractContextLoader#modifyLocations
* @see org.springframework.test.context.support.AbstractContextLoader#modifyLocations
* @throws UnsupportedOperationException
*/
@Override
@ -100,7 +120,7 @@ public class AnnotationConfigWebContextLoader extends AbstractGenericWebContextL
* not as a legacy {@link org.springframework.test.context.ContextLoader ContextLoader}.
* Consequently, this method is not supported.
*
* @see AbstractContextLoader#generateDefaultLocations
* @see org.springframework.test.context.support.AbstractContextLoader#generateDefaultLocations
* @throws UnsupportedOperationException
*/
@Override
@ -115,7 +135,7 @@ public class AnnotationConfigWebContextLoader extends AbstractGenericWebContextL
* not as a legacy {@link org.springframework.test.context.ContextLoader ContextLoader}.
* Consequently, this method is not supported.
*
* @see AbstractContextLoader#getResourceSuffix
* @see org.springframework.test.context.support.AbstractContextLoader#getResourceSuffix
* @throws UnsupportedOperationException
*/
@Override
@ -127,7 +147,7 @@ public class AnnotationConfigWebContextLoader extends AbstractGenericWebContextL
// --- AbstractGenericWebContextLoader -------------------------------------
/**
* Register classes in the supplied {@link GenericWebApplicationContext context}
* Register classes in the supplied {@linkplain GenericWebApplicationContext context}
* from the classes in the supplied {@link WebMergedContextConfiguration}.
*
* <p>Each class must represent an <em>annotated class</em>. An

View File

@ -20,7 +20,8 @@ import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.web.context.support.GenericWebApplicationContext;
/**
* TODO [SPR-9864] Document GenericXmlWebContextLoader.
* Concrete implementation of {@link AbstractGenericWebContextLoader} that loads
* bean definitions from XML resources.
*
* @author Sam Brannen
* @since 3.2
@ -28,9 +29,9 @@ import org.springframework.web.context.support.GenericWebApplicationContext;
public class GenericXmlWebContextLoader extends AbstractGenericWebContextLoader {
/**
* TODO [SPR-9864] Document overridden loadBeanDefinitions().
* Loads bean definitions using an {@link XmlBeanDefinitionReader}.
*
* @see org.springframework.test.context.web.AbstractGenericWebContextLoader#loadBeanDefinitions(org.springframework.web.context.support.GenericWebApplicationContext, org.springframework.test.context.web.WebMergedContextConfiguration)
* @see AbstractGenericWebContextLoader#loadBeanDefinitions()
*/
@Override
protected void loadBeanDefinitions(GenericWebApplicationContext context,

View File

@ -20,6 +20,7 @@ import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
@ -34,7 +35,24 @@ import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletWebRequest;
/**
* TODO [SPR-9864] Document ServletTestExecutionListener.
* {@code TestExecutionListener} which provides mock Servlet API support to
* {@link WebApplicationContext WebApplicationContexts} loaded by the <em>Spring
* TestContext Framework</em>.
*
* <p>Specifically, {@code ServletTestExecutionListener} sets up thread-local
* state via Spring Web's {@link RequestContextHolder} during {@linkplain
* #prepareTestInstance(TestContext) test instance preparation} and {@linkplain
* #beforeTestMethod(TestContext) before each test method} and creates a {@link
* MockHttpServletRequest}, {@link MockHttpServletResponse}, and
* {@link ServletWebRequest} based on the {@link MockServletContext} present in
* the {@code WebApplicationContext}. This listener also ensures that the
* {@code MockHttpServletResponse} and {@code ServletWebRequest} can be injected
* into the test instance, and once the test is complete this listener {@linkplain
* #afterTestMethod(TestContext) cleans up} thread-local state.
*
* <p>Note that {@code ServletTestExecutionListener} is enabled by default but
* takes no action if the {@link ApplicationContext} loaded for the current test
* is not a {@link WebApplicationContext}.
*
* @author Sam Brannen
* @since 3.2
@ -43,27 +61,33 @@ public class ServletTestExecutionListener extends AbstractTestExecutionListener
private static final Log logger = LogFactory.getLog(ServletTestExecutionListener.class);
/**
* TODO [SPR-9864] Document overridden prepareTestInstance().
* Sets up thread-local state during the <em>test instance preparation</em>
* callback phase via Spring Web's {@link RequestContextHolder}.
*
* @see TestExecutionListener#prepareTestInstance(TestContext)
* @see #setUpRequestContextIfNecessary(TestContext)
*/
public void prepareTestInstance(TestContext testContext) throws Exception {
setUpRequestContextIfNecessary(testContext);
}
/**
* TODO [SPR-9864] Document overridden beforeTestMethod().
* Sets up thread-local state before each test method via Spring Web's
* {@link RequestContextHolder}.
*
* @see TestExecutionListener#beforeTestMethod(TestContext)
* @see #setUpRequestContextIfNecessary(TestContext)
*/
public void beforeTestMethod(TestContext testContext) throws Exception {
setUpRequestContextIfNecessary(testContext);
}
/**
* TODO [SPR-9864] Document overridden afterTestMethod().
* Cleans up thread-local state after each test method by {@linkplain
* RequestContextHolder#resetRequestAttributes() resetting} Spring Web's
* {@code RequestContextHolder}.
*
* @see TestExecutionListener#afterTestMethod(TestContext)
*/
@ -74,11 +98,6 @@ public class ServletTestExecutionListener extends AbstractTestExecutionListener
RequestContextHolder.resetRequestAttributes();
}
/**
* TODO [SPR-9864] Document setUpRequestContext().
*
* @param testContext
*/
private void setUpRequestContextIfNecessary(TestContext testContext) {
ApplicationContext context = testContext.getApplicationContext();

View File

@ -24,10 +24,25 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* TODO [SPR-9864] Document WebAppConfiguration.
* {@code @WebAppConfiguration} is a class-level annotation that is used to
* declare that the {@code ApplicationContext} loaded for an integration test
* should be a {@link org.springframework.web.context.WebApplicationContext
* WebApplicationContext}.
*
* <p>The mere presence of {@code @WebAppConfiguration} on a test class ensures
* that a {@code WebApplicationContext} will be loaded for the test using a default
* for the path to the root of the web application. To override the default,
* specify an explicit resource path via the {@link #value} attribute.
*
* <p>Note that {@code @WebAppConfiguration} must be used in conjunction with
* {@link org.springframework.test.context.ContextConfiguration @ContextConfiguration},
* either within a single test class or within a test class hierarchy.
*
* @author Sam Brannen
* @since 3.2
* @see org.springframework.web.context.WebApplicationContext
* @see org.springframework.test.context.ContextConfiguration
* @see ServletTestExecutionListener
*/
@Documented
@Inherited
@ -36,9 +51,15 @@ import java.lang.annotation.Target;
public @interface WebAppConfiguration {
/**
* The root directory of the web application (i.e., WAR); should not end with a slash.
*
* <p>Defaults to {@code "src/main/webapp"}.
* The resource path to the root directory of the web application.
*
* <p>A path that does not include a Spring resource prefix (e.g., {@code classpath:},
* {@code file:}, etc.) will be interpreted as a file system resource, and a
* path should not end with a slash.
*
* <p>Defaults to {@code "src/main/webapp"} as a file system resource. Note
* that this is the standard directory for the root of a web application in
* a project that follows the standard Maven project layout for a WAR.
*/
String value() default "src/main/webapp";

View File

@ -27,10 +27,28 @@ import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* TODO [SPR-9864] Document WebMergedContextConfiguration.
* {@code WebMergedContextConfiguration} encapsulates the <em>merged</em>
* context configuration declared on a test class and all of its superclasses
* via {@link org.springframework.test.context.ContextConfiguration @ContextConfiguration},
* {@link WebAppConfiguration @WebAppConfiguration}, and
* {@link org.springframework.test.context.ActiveProfiles @ActiveProfiles}.
*
* <p>{@code WebMergedContextConfiguration} extends the contract of
* {@link MergedContextConfiguration} by adding support for the {@link
* #getResourceBasePath() resource base path} configured via {@code @WebAppConfiguration}.
* This allows the {@link org.springframework.test.context.TestContext TestContext}
* to properly cache the corresponding {@link
* org.springframework.web.context.WebApplicationContext WebApplicationContext}
* that was loaded using properties of this {@code WebMergedContextConfiguration}.
*
* @author Sam Brannen
* @since 3.2
* @see WebAppConfiguration
* @see MergedContextConfiguration
* @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.ActiveProfiles
* @see org.springframework.test.context.ContextConfigurationAttributes
* @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration)
*/
public class WebMergedContextConfiguration extends MergedContextConfiguration {
@ -40,7 +58,25 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
/**
* TODO [SPR-9864] Document WebMergedContextConfiguration constructor.
* Create a new {@code WebMergedContextConfiguration} instance for the
* supplied test class, resource locations, annotated classes, context
* initializers, active profiles, resource base path, and {@code ContextLoader}.
*
* <p>If a <code>null</code> value is supplied for <code>locations</code>,
* <code>classes</code>, or <code>activeProfiles</code> an empty array will
* be stored instead. If a <code>null</code> value is supplied for the
* <code>contextInitializerClasses</code> an empty set will be stored instead.
* If an <em>empty</em> value is supplied for the <code>resourceBasePath</code>
* an empty string will be used. Furthermore, active profiles will be sorted,
* and duplicate profiles will be removed.
*
* @param testClass the test class for which the configuration was merged
* @param locations the merged resource locations
* @param classes the merged annotated classes
* @param contextInitializerClasses the merged context initializer classes
* @param activeProfiles the merged active bean definition profiles
* @param resourceBasePath the resource path to the root directory of the web application
* @param contextLoader the resolved <code>ContextLoader</code>
*/
public WebMergedContextConfiguration(
Class<?> testClass,
@ -55,7 +91,9 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
}
/**
* TODO [SPR-9864] Document getResourceBasePath().
* Get the resource path to the root directory of the web application for the
* {@linkplain #getTestClass() test class}, configured via {@code @WebAppConfiguration}.
* @see WebAppConfiguration
*/
public String getResourceBasePath() {
return this.resourceBasePath;