Description
Tomasz Wysocki opened SPR-5613 and commented
Status Quo
Currently the TestContext framework supports creating only flat, non-hierarchical contexts. There is no easy way to create contexts with parent-child relationships.
Goals
- Add support for creating a test context with a parent context.
- Configuration in the TestContext framework should allow for any number of levels in the context hierarchy.
- Different levels in the context hierarchy may have different types of contexts (e.g., XML or annotation classes).
Example Hierarchies
- Root
WebApplicationContext
<-- DispatcherWebApplicationContext
- EAR
ApplicationContext
<-- RootWebApplicationContext
<-- DispatcherWebApplicationContext
Deliverables
- Introduce a new
@ContextHierarchy
annotation that can contain nested@ContextConfiguration
declarations - Introduce a new
name
attribute in@ContextConfiguration
that can be used for merging or overriding named@ContextConfiguration
elements in the context hierarchy - Assemble the context hierarchy for a given test class based on the levels defined in
@ContextHierarchy
in a single test class - Assemble the context hierarchy for a given test class based on the levels defined in
@ContextHierarchy
and@ContextConfiguration
within the test class hierarchy - Support merging of configuration files or classes at any level in the hierarchy via the
name
attribute of@ContextConfiguration
- Support overriding of configuration files or classes at any level in the hierarchy via the
name
andinheritLocations
attributes of@ContextConfiguration
- Cache each individual context within a hierarchy
- Support dirtying of the context hierarchy, including dirtying of any other affected hierarchies that share a common ancestor context
- Detect default XML resource location or default annotated classes, if feasible
Implementation Considerations
-
MergedContextConfiguration
should have a reference to the parentMergedContextConfiguration
(i.e., aprivate final
field) -
MergedContextConfiguration
should provide apublic ApplicationContext getParentApplicationContext()
method thatSmartContextLoader
instances can use to retrieve and set the parentApplicationContext
-
MergedContextConfiguration
will need an internal reference to the context cache (or at least a way to retrieve the parent context from the cache)
-
Pseudocode Examples
Single Test Class with Context Hierarchy
@RunWith(SpringJUnit4ClassRunner.class)
@ContextHierarchy({
@ContextConfiguration("parent.xml"),
@ContextConfiguration("child.xml")
})
public class AppCtxHierarchyTests {}
Resulting Hierarchies
+------------+
| parent.xml |
+------------+
^
|
+------------+
| child.xml |
+------------+
Class Hierarchy with Implicit Parent Context
@RunWith(SpringJUnit4ClassRunner.class)
@ContextHierarchy(@ContextConfiguration(classes = AppConfig.class))
public abstract class AbstractTests {}
@ContextHierarchy(@ContextConfiguration("/A-config.xml"))
public class A extends AbstractTests {}
@ContextHierarchy(@ContextConfiguration("/B-config.xml"))
public class B extends AbstractTests {}
Resulting Hierarchies
+-----------------+
| AppConfig.class |
+-----------------+
^
|
+-----------------+
| A-config.xml |
+-----------------+
+-----------------+
| AppConfig.class |
+-----------------+
^
|
+-----------------+
| B-config.xml |
+-----------------+
Class Hierarchy with Bare @ContextConfiguration
in a Superclass
In this scenario it is assumed that AbstractTests
existed prior to the introduction of @ContextHierarchy
support and that the author does not wish to (or cannot) modify AbstractTests
to declare a @ContextHierarchy
.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public abstract class AbstractTests {}
@ContextHierarchy(@ContextConfiguration("/A-config.xml"))
public class A extends AbstractTests {}
Resulting Hierarchies
+-----------------+
| AppConfig.class |
+-----------------+
^
|
+-----------------+
| A-config.xml |
+-----------------+
Class Hierarchy with Bare @ContextConfiguration
in a Subclass
This scenario is not necessarily recommended, but it should still be supported for the sake of consistency.
Ideally, if the author of a test class knows that the context for the test class should take part in a context hierarchy, then the author should explicitly declare @ContextConfiguration
within @ContextHierarchy
.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextHierarchy(@ContextConfiguration(classes = AppConfig.class))
public abstract class AbstractTests {}
@ContextConfiguration("/A-config.xml")
public class A extends AbstractTests {}
Resulting Hierarchies
+-----------------+
| AppConfig.class |
+-----------------+
^
|
+-----------------+
| A-config.xml |
+-----------------+
Class Hierarchy with Merged Configuration
@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 {}
Resulting Hierarchies
+----------------+
| app-config.xml |
+----------------+
^
|
+-----------------+
| user-config.xml |
+-----------------+
+----------------+
| app-config.xml |
+----------------+
^
|
+-----------------------------------+
| user-config.xml, order-config.xml |
+-----------------------------------+
Class Hierarchy with Overridden Configuration
@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 {}
Resulting Hierarchies
+----------------+
| app-config.xml |
+----------------+
^
|
+-----------------+
| user-config.xml |
+-----------------+
+----------------+
| app-config.xml |
+----------------+
^
|
+----------------------+
| test-user-config.xml |
+----------------------+
Affects: 2.5.6
Issue Links:
- Support WebApplicationContext hierarchies in the TestContext Framework [SPR-9863] #14496 Support WebApplicationContext hierarchies in the TestContext Framework ("is depended on by")
- Support loading WebApplicationContexts with the TestContext Framework [SPR-5243] #9917 Support loading WebApplicationContexts with the TestContext Framework ("is depended on by")
- Document context hierarchy support in the TestContext framework [SPR-10357] #14989 Document context hierarchy support in the TestContext framework ("is depended on by")
- Load dedicated child ApplicationContext for test instance in the TestContext framework [SPR-4632] #9309 Load dedicated child ApplicationContext for test instance in the TestContext framework
- TestContext to become subclassable [SPR-5428] #10102 TestContext to become subclassable ("supersedes")
Referenced from: commits eefd1c4, 4c5d771, 98074e7
10 votes, 11 watchers