Skip to content

Provide support for context hierarchies in the TestContext Framework [SPR-5613] #10284

Closed
@spring-projects-issues

Description

@spring-projects-issues

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 <-- Dispatcher WebApplicationContext
  • EAR ApplicationContext <-- Root WebApplicationContext <-- Dispatcher WebApplicationContext

Deliverables

  1. Introduce a new @ContextHierarchy annotation that can contain nested @ContextConfiguration declarations
  2. Introduce a new name attribute in @ContextConfiguration that can be used for merging or overriding named @ContextConfiguration elements in the context hierarchy
  3. Assemble the context hierarchy for a given test class based on the levels defined in @ContextHierarchy in a single test class
  4. Assemble the context hierarchy for a given test class based on the levels defined in @ContextHierarchy and @ContextConfiguration within the test class hierarchy
  5. Support merging of configuration files or classes at any level in the hierarchy via the name attribute of @ContextConfiguration
  6. Support overriding of configuration files or classes at any level in the hierarchy via the name and inheritLocations attributes of @ContextConfiguration
  7. Cache each individual context within a hierarchy
  8. Support dirtying of the context hierarchy, including dirtying of any other affected hierarchies that share a common ancestor context
  9. Detect default XML resource location or default annotated classes, if feasible

Implementation Considerations

  • MergedContextConfiguration should have a reference to the parent MergedContextConfiguration (i.e., a private final field)
  • MergedContextConfiguration should provide a public ApplicationContext getParentApplicationContext() method that SmartContextLoader instances can use to retrieve and set the parent ApplicationContext
    • 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:

Referenced from: commits eefd1c4, 4c5d771, 98074e7

10 votes, 11 watchers

Metadata

Metadata

Assignees

Labels

has: votes-jiraIssues migrated from JIRA with more than 10 votes at the time of importin: testIssues in the test moduletype: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions