Add support for creating test contexts with parent context #43

Closed
wants to merge 1 commit into
from

5 participants

@ttddyy

Hello,

I created "@ParentContextConfiguration" to support parent test contexts in spring-test framework.

Sample:

  @ParentContextConfiguration("parent-context.xml")
  @ContextConfiguration("child-context.xml")
  @RunWith(SpringJUnit4ClassRunner.class)
  public class SomeTests {

      @Autowired
      protected ApplicationContext applicationContext;

      // applicationContext.getParent() returns the parent app context
  }

Parent context will be shared across the test classes if they are annotated to use parent context and have same configurations(xml locations, configuration classes, etc). It uses existing context caching mechanism.
I also added "parent" attribute to @DirtiesContext annotation in order to close the parent context if required. When "parent=true" is set on @DirtiesContext, DirtiesContextTestExecutionListener will close the parent application context as well as child contexts using the specified parent context.

Changes:

  • created @ParentContextConfiguration to configure the parent application context.

  • reused the @ContextConfigurationAttributes to represent both @ContextConfiguration and @ParentContextConfiguration

  • changed ContextLoader SPI to pass a parent ApplicationContext

  • refactored ContextLoaderUtils to use "getConfigurationAttributes()" to resolve the context loader class and configuration attribute in a similar manner.

  • created ContextCacheKey class which contains two MergedContextConfiguration (one for parent, one for child) as a key of ContextCache.

  • added "parent" attribute on @DirtiesContext

  • @DirtiesContext(parent=true) will remove parent app context and all child app contexts using that parent context from the cache

  • unit tests

Issue: SPR-5613

Submitted the CLA

Thanks,

Tadaya Tsuyukubo Add support for creating test contexts with parent context
Created @ParentContextConfiguration to support parent test contexts
in spring-test framework.

Parent context will be shared across the test classes if they are
annotated to use parent context and have same configurations(xml
locations, configuration classes, etc). It also uses existing context
caching mechanism.
I also added "parent" attribute to @DirtiesContext annotation in order
to close the parent context if required. When "parent=true" is set on
@DirtiesContext, DirtiesContextTestExecutionListener will close the
parent application context as well as child contexts using the specified
parent context.

Changes:

- created @ParentContextConfiguration to configure the parent
  application context.

- reused the @ContextConfigurationAttributes to represent both
  @ContextConfiguration and @ParentContextConfiguration

- changed ContextLoader SPI to pass a parent ApplicationContext

- refactored ContextLoaderUtils to use "getConfigurationAttributes()"
  to resolve the context loader class and configuration attribute.

- created ContextCacheKey class which contains two
  MergedContextConfiguration (one for parent, one for child) as a key
  of ContextCache.

- added "parent" attribute on @DirtiesContext

- @DirtiesContext(parent=true) will remove parent app context and all
  child app contexts using that parent context from the cache

- unit tests

Issue: SPR-5613
e2a1bb8
@cbeams

Thanks for the submission, Tadaya. @sbrannen, can you take a look at this?

Ideally, we would avoid the introduction of the @ParentContextConfiguration annotation, perhaps in favor of a 'parent' attribute that can accept a nested @ContextConfiguration, e.g.

@ContextConfiguration(
    locations = "child-context.xml",
    parent = @ContextConfiguration("parent-context.xml"))
@RunWith(SpringJUnit4ClassRunner.class)
public class SomeTests {

    @Autowired
    protected ApplicationContext applicationContext;
    // applicationContext.getParent() returns the parent app context
}

Unfortunately, however, the above cannot work because it creates a cycle in the definition of the ContextConfiguration annotation (actually doesn't compile). Still, perhaps we can come up with something a bit more elegant than yet another annotation here. I imagine Sam has already thought about this quite a bit, so I'll turn it over to him for comments.

@rstoyanchev

Maybe an array of @ContextConfiguration annotations -- the first one is the parent of the second one, and so on...

@ContextHierarchy({
    @ContextConfiguration("parent-context.xml"),
    @ContextConfiguration("child-context.xml")
})
public class SomeTests {

}
@cbeams
@rstoyanchev

Also at the moment spring-test-mvc has a programmatic way of doing the equivalent of @ContextConfiguration. Given that parent contexts will also need to be supported there, I'm beginning to wonder if the TestContext framework couldn't offer a code-based alternative to @ContextConfiguration, which spring-test-mvc could then build on. Don't know enough about @RunWith but perhaps the test could implement a callback interface such as ApplicationContextInitializer?

@cbeams
@ttddyy

I think we also need to consider the inheritance.
When @ContextConfiguration has "inheritLocations=true", it traverse the parent classes and merge the annotation attributes.

How about adding "order" attribute, so that child class can specify which context config to override.

@ContextHierarchy({
  @ContextConfiguration(value="parent-context.xml", order=0),
  @ContextConfiguration(value="child-context.xml", order=1)
})
public class BaseTests {
}

@ContextHierarchy({
  // merge the child context, not the parent one
  @ContextConfiguration(value="another-child-context.xml", order=1, inheritLocations=true),
})
public class ConcreteTests extends BaseTests {
}

not sure, more than two levels of parent-child hierarchy is really practical or not.

Thanks,

@sbrannen sbrannen was assigned May 17, 2012
@snicoll
Spring member

SPR-5613 has been resolved as from 3.2.2

@snicoll snicoll closed this Apr 17, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment