diff --git a/src/reference/docbook/new-in-3.2.xml b/src/reference/docbook/new-in-3.2.xml
index 8d403c6ead..dc53ce9777 100644
--- a/src/reference/docbook/new-in-3.2.xml
+++ b/src/reference/docbook/new-in-3.2.xml
@@ -274,6 +274,12 @@
WebApplicationContext in integration tests
+
+ Configuring context hierarchies
+ in integration tests
+
+
Testing request and
session scoped beans
diff --git a/src/reference/docbook/testing.xml b/src/reference/docbook/testing.xml
index e5bb9aafd7..bb26dc0c54 100644
--- a/src/reference/docbook/testing.xml
+++ b/src/reference/docbook/testing.xml
@@ -291,9 +291,9 @@
framework can be configured to reload the configuration and rebuild the
application context before executing the next test.
- See context management and caching with the TestContext
- framework.
+ See and with the TestContext
+ framework.
@@ -511,10 +511,9 @@ public class CustomLoaderXmlApplicationContextTests {
declared by superclasses by default.
- See Context
- management and caching and the Javadoc for
- @ContextConfiguration for further
- details.
+ See and the
+ Javadoc for @ContextConfiguration for
+ further details.
@@ -563,6 +562,50 @@ public class WebAppTests {
further details.
+
+
+ @ContextHierarchy
+
+ A class-level annotation that is used to define a hierarchy of
+ ApplicationContexts for integration
+ tests. @ContextHierarchy should be
+ declared with a list of one or more
+ @ContextConfiguration instances, each
+ of which defines a level in the context hierarchy. The following
+ examples demonstrate the use of
+ @ContextHierarchy within a single
+ test class; however,
+ @ContextHierarchy can also be used
+ within a test class hierarchy.
+
+ @ContextHierarchy({
+ @ContextConfiguration("/parent-config.xml"),
+ @ContextConfiguration("/child-config.xml")
+})
+public class ContextHierarchyTests {
+ // class body...
+}
+
+ @WebAppConfiguration
+@ContextHierarchy({
+ @ContextConfiguration(classes = AppConfig.class),
+ @ContextConfiguration(classes = WebConfig.class)
+})
+public class WebIntegrationTests {
+ // class body...
+}
+
+ If you need to merge or override the configuration for a given
+ level of the context hierarchy within a test class hierarchy, you
+ must explicitly name that level by supplying the same value to the
+ name attribute in
+ @ContextConfiguration at each
+ corresponding level in the class hierarchy. See and the
+ Javadoc for @ContextHierarchy for
+ further examples.
+
+
@ActiveProfiles
@@ -590,11 +633,9 @@ public class DeveloperIntegrationTests {
profiles declared by superclasses by default.
- See Context
- configuration with environment profiles and the Javadoc for
- @ActiveProfiles for examples and
- further details.
+ See
+ and the Javadoc for @ActiveProfiles
+ for examples and further details.
@@ -603,66 +644,98 @@ public class DeveloperIntegrationTests {
Indicates that the underlying Spring
ApplicationContext has been
- dirtied (i.e., modified or corrupted in some
- manner) during the execution of a test and should be closed,
- regardless of whether the test passed.
- @DirtiesContext is supported in the
- following scenarios:
+ dirtied during the execution of a test (i.e.,
+ modified or corrupted in some manner — for example, by changing the
+ state of a singleton bean) and should be closed, regardless of
+ whether the test passed. When an application context is marked
+ dirty, it is removed from the testing
+ framework's cache and closed. As a consequence, the underlying
+ Spring container will be rebuilt for any subsequent test that
+ requires a context with the same configuration metadata.
+
+ @DirtiesContext can be used as
+ both a class-level and method-level annotation within the same test
+ class. In such scenarios, the
+ ApplicationContext is marked as
+ dirty after any such annotated method as well
+ as after the entire class. If the ClassMode
+ is set to AFTER_EACH_TEST_METHOD, the context is
+ marked dirty after each test method in the class.
+
+ The following examples explain when the context would be
+ dirtied for various configuration scenarios:After the current test class, when declared on a class
- with class mode set to AFTER_CLASS, which is
- the default class mode.
+ with class mode set to AFTER_CLASS (i.e., the
+ default class mode).
+
+ @DirtiesContext
+public class ContextDirtyingTests {
+ // some tests that result in the Spring container being dirtied
+}After each test method in the current test class, when
declared on a class with class mode set to
- AFTER_EACH_TEST_METHOD.
+ AFTER_EACH_TEST_METHOD.@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+public class ContextDirtyingTests {
+ // some tests that result in the Spring container being dirtied
+}After the current test, when declared on a method.
-
-
- Use this annotation if a test has modified the context (for
- example, by replacing a bean definition). Subsequent tests are
- supplied a new context.
-
- With JUnit 4.5+ or TestNG you can use
- @DirtiesContext as both a class-level
- and method-level annotation within the same test class. In such
- scenarios, the ApplicationContext is
- marked as dirty after any such annotated method
- as well as after the entire class. If the
- ClassMode is set to
- AFTER_EACH_TEST_METHOD, the context is marked
- dirty after each test method in the class.
-
- @DirtiesContext
-public class ContextDirtyingTests {
- // some tests that result in the Spring container being dirtied
-}
-
- @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
-public class ContextDirtyingTests {
- // some tests that result in the Spring container being dirtied
-}
-
- @DirtiesContext
+ @DirtiesContext
@Test
public void testProcessWhichDirtiesAppCtx() {
// some logic that results in the Spring container being dirtied
}
+
+
- When an application context is marked
- dirty, it is removed from the testing
- framework's cache and closed; thus the underlying Spring container
- is rebuilt for any subsequent test that requires a context with the
- same configuration metadata.
+ If @DirtiesContext is used in a
+ test whose context is configured as part of a context hierarchy via
+ @ContextHierarchy, the
+ hierarchyMode flag can be used to control how the
+ context cache is cleared. By default an
+ exhaustive algorithm will be used that clears
+ the context cache including not only the current level but also all
+ other context hierarchies that share an ancestor context common to
+ the current test; all
+ ApplicationContexts that reside in a
+ sub-hierarchy of the common ancestor context will be removed from
+ the context cache and closed. If the exhaustive
+ algorithm is overkill for a particular use case, the simpler
+ current level algorithm can be specified
+ instead, as seen below.
+
+ @ContextHierarchy({
+ @ContextConfiguration("/parent-config.xml"),
+ @ContextConfiguration("/child-config.xml")
+})
+public class BaseTests {
+ // class body...
+}
+
+public class ExtendedTests extends BaseTests {
+
+ @Test
+ @DirtiesContext(hierarchyMode = HierarchyMode.CURRENT_LEVEL)
+ public void test() {
+ // some logic that results in the child context being dirtied
+ }
+}
+
+ For further details regarding the
+ EXHAUSTIVE and
+ CURRENT_LEVEL algorithms see the Javadoc for
+ DirtiesContext.HierarchyMode.
@@ -1918,7 +1991,7 @@ public class WacTests {
@Configuration classes).
- Default Resource Semantics
+ Default resource semantics@RunWith(SpringJUnit4ClassRunner.class)
@@ -1945,7 +2018,7 @@ public class WacTests {
locations are classpath based.
- Explicit Resource Semantics
+ Explicit resource semantics@RunWith(SpringJUnit4ClassRunner.class)
@@ -2002,7 +2075,7 @@ public class WacTests {
ServletTestExecutionListener.
- Injecting Mocks
+ Injecting mocks@WebAppConfiguration
@ContextConfiguration
@@ -2135,6 +2208,198 @@ public class WacTests {
DirtiesContextTestExecutionListener which is
enabled by default.
+
+
+ Context hierarchies
+
+ When writing integration tests that rely on a loaded Spring
+ ApplicationContext, it is often
+ sufficient to test against a single context; however, there are times
+ when it is beneficial or even necessary to test against a hierarchy of
+ ApplicationContexts. For example, if
+ you are developing a Spring MVC web application you will typically
+ have a root WebApplicationContext
+ loaded via Spring's ContextLoaderListener and a
+ child WebApplicationContext loaded via
+ Spring's DispatcherServlet. This results in a
+ parent-child context hierarchy where shared components and
+ infrastructure configuration are declared in the root context and
+ consumed in the child context by web-specific components. Another use
+ case can be found in Spring Batch applications where you often have a
+ parent context that provides configuration for shared batch
+ infrastructure and a child context for the configuration of a specific
+ batch job.
+
+ As of Spring Framework 3.2.2, it is possible to write
+ integration tests that use context hierarchies by declaring context
+ configuration via the @ContextHierarchy
+ annotation, either on an individual test class or within a test class
+ hierarchy. If a context hierarchy is declared on multiple classes
+ within a test class hierarchy it is also possible to merge or override
+ the context configuration for a specific, named level in the context
+ hierarchy. When merging configuration for a given level in the
+ hierarchy the configuration resource type (i.e., XML configuration
+ files or annotated classes) must be consistent; otherwise, it is
+ perfectly acceptable to have different levels in a context hierarchy
+ configured using different resource types.
+
+ The following JUnit-based examples demonstrate common
+ configuration scenarios for integration tests that require the use of
+ context hierarchies.
+
+
+ Single test class with context hierarchy
+
+ ControllerIntegrationTests represents a
+ typical integration testing scenario for a Spring MVC web
+ application by declaring a context hierarchy consisting of two
+ levels, one for the root WebApplicationContext
+ (loaded using the TestAppConfig
+ @Configuration class) and one for the
+ dispatcher servlet
+ WebApplicationContext (loaded using
+ the WebConfig
+ @Configuration class). The
+ WebApplicationContext that is
+ autowired into the test instance is the one for
+ the child context (i.e., the lowest context in the
+ hierarchy).
+
+ @RunWith(SpringJUnit4ClassRunner.class)
+@WebAppConfiguration
+@ContextHierarchy({
+ @ContextConfiguration(classes = TestAppConfig.class),
+ @ContextConfiguration(classes = WebConfig.class)
+})
+public class ControllerIntegrationTests {
+
+ @Autowired
+ private WebApplicationContext wac;
+
+ // ...
+}
+
+
+
+ Class hierarchy with implicit parent context
+
+ The following test classes define a context hierarchy within a
+ test class hierarchy. AbstractWebTests
+ declares the configuration for a root
+ WebApplicationContext in a
+ Spring-powered web application. Note, however, that
+ AbstractWebTests does not declare
+ @ContextHierarchy; consequently,
+ subclasses of AbstractWebTests can optionally
+ participate in a context hierarchy or simply follow the standard
+ semantics for @ContextConfiguration.
+ SoapWebServiceTests and
+ RestWebServiceTests both extend
+ AbstractWebTests and define a context
+ hierarchy via @ContextHierarchy. The
+ result is that three application contexts will be loaded (one for
+ each declaration of
+ @ContextConfiguration), and the
+ application context loaded based on the configuration in
+ AbstractWebTests will be set as the parent
+ context for each of the contexts loaded for the concrete
+ subclasses.
+
+ @RunWith(SpringJUnit4ClassRunner.class)
+@WebAppConfiguration
+@ContextConfiguration("file:src/main/webapp/WEB-INF/applicationContext.xml")
+public abstract class AbstractWebTests {}
+
+@ContextHierarchy(@ContextConfiguration("/spring/soap-ws-config.xml")
+public class SoapWebServiceTests extends AbstractWebTests {}
+
+@ContextHierarchy(@ContextConfiguration("/spring/rest-ws-config.xml")
+public class RestWebServiceTests extends AbstractWebTests {}
+
+
+
+ Class hierarchy with merged context hierarchy
+ configuration
+
+ The following classes demonstrate the use of
+ named hierarchy levels in order to
+ merge the configuration for specific levels in
+ a context hierarchy. BaseTests defines two
+ levels in the hierarchy, parent and
+ child. ExtendedTests
+ extends BaseTests and instructs the Spring
+ TestContext Framework to merge the context configuration for the
+ child hierarchy level, simply by ensuring that
+ the names declared via
+ ContextConfiguration's
+ name attribute are both
+ "child". The result is that three application
+ contexts will be loaded: one for
+ "/app-config.xml", one for
+ "/user-config.xml", and one for
+ {"/user-config.xml", "/order-config.xml"}. As
+ with the previous example, the application context loaded from
+ "/app-config.xml" will be set as the parent
+ context for the contexts loaded from
+ "/user-config.xml" and
+ {"/user-config.xml", "/order-config.xml"}.
+
+ @RunWith(SpringJUnit4ClassRunner.class)
+@ContextHierarchy({
+ @ContextConfiguration(name = "parent", locations = "/app-config.xml"),
+ @ContextConfiguration(name = "child", locations = "/user-config.xml")
+})
+public class BaseTests {}
+
+@ContextHierarchy(
+ @ContextConfiguration(name = "child", locations = "/order-config.xml")
+)
+public class ExtendedTests extends BaseTests {}
+
+
+
+ Class hierarchy with overridden context hierarchy
+ configuration
+
+ In contrast to the previous example, this example demonstrates
+ how to override the configuration for a given
+ named level in a context hierarchy by setting
+ ContextConfiguration's
+ inheritLocations flag to
+ false. Consequently, the application context for
+ ExtendedTests will be loaded only from
+ "/test-user-config.xml" and will have its parent
+ set to the context loaded from
+ "/app-config.xml".
+
+ @RunWith(SpringJUnit4ClassRunner.class)
+@ContextHierarchy({
+ @ContextConfiguration(name = "parent", locations = "/app-config.xml"),
+ @ContextConfiguration(name = "child", locations = "/user-config.xml")
+})
+public class BaseTests {}
+
+@ContextHierarchy(
+ @ContextConfiguration(
+ name = "child",
+ locations = "/test-user-config.xml",
+ inheritLocations = false
+))
+public class ExtendedTests extends BaseTests {}
+
+
+
+ Dirtying a context within a context hierarchy
+
+ If @DirtiesContext is used in a
+ test whose context is configured as part of a context hierarchy, the
+ hierarchyMode flag can be used to control how the
+ context cache is cleared. For further details consult the discussion
+ of @DirtiesContext in and the Javadoc
+ for @DirtiesContext.
+
+