Uploaded image for project: 'Spring Framework'
  1. Spring Framework
  2. SPR-5613

Provide support for context hierarchies in the TestContext Framework

    Details

    • Type: New Feature
    • Status: Closed
    • Priority: Major
    • Resolution: Complete
    • Affects Version/s: 2.5.6
    • Fix Version/s: 3.2.2
    • Component/s: Test
    • Labels:
      None
    • Last commented by a User:
      false

      Description

      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 |
      +----------------------+
      

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                sbrannen Sam Brannen
                Reporter:
                tawek Tomasz Wysocki
                Last updater:
                Sam Brannen
              • Votes:
                10 Vote for this issue
                Watchers:
                11 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Days since last comment:
                  5 years, 8 weeks ago

                  Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - 0d
                  0d
                  Logged:
                  Time Spent - 1d
                  1d