Skip to content

Provide support for ApplicationContextInitializers in the TestContext framework [SPR-9011] #13650

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
3 tasks done
spring-projects-issues opened this issue Jan 9, 2012 · 8 comments
Assignees
Labels
has: votes-jira Issues migrated from JIRA with more than 10 votes at the time of import in: test Issues in the test module type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Jan 9, 2012

Rossen Stoyanchev opened SPR-9011 and commented

Status Quo

Starting with Spring 3.1 applications can specify contextInitializerClasses via context-param and init-param in web.xml.


Goals

For comprehensive testing it should be possible to re-use ApplicationContextInitializer instances in tests as well.

This could be done at the @ContextConfiguration level by allowing an array of ACI types to be specified, and the TCF would allow each to visit the ApplicationContext at the right time.


Deliverables

[x] Introduce a new initializers attribute in @ContextConfiguration.


     ```

Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>[] initializers() default {};

1. [x] Introduce a new `inheritInitializers` attribute in `@ContextConfiguration`.
   - ```
boolean inheritInitializers() default true;
  1. Allow a context to be loaded solely via a custom ApplicationContextInitializer (i.e., without locations or classes)

  2. Initializers must be included in MergedContextConfiguration for determining the context cache key.

  3. Invoke initializers within existing SmartContextLoader implementations.

    • for example, in AbstractGenericContextLoader.loadContext(...) methods

    [x] per the contract defined in the Javadoc for ApplicationContextInitializer: ApplicationContextInitializer processors are encouraged to detect whether Spring's Ordered interface has been implemented or if the @Order annotation is present and to sort instances accordingly if so prior to invocation.

           ```
    
    

Collections.sort(initializerInstances, new AnnotationAwareOrderComparator());

1. [x] Document in Javadoc
1. [x] Document in the reference manual

----
#### Pseudocode Examples

```java 
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
    locations = "/app-config.xml",
    initializers = CustomInitializer.class)
public class ApplicationContextInitializerTests {}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
    locations = "/app-config.xml",
    initializers = {PropertySourceInitializer.class, ProfileInitializer.class})
public class ApplicationContextInitializerTests {}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
    classes = BaseConfig.class,
    initializers = BaseInitializer.class)
public class BaseTest {}

@ContextConfiguration(
    classes = ExtendedConfig.class,
    initializers = ExtendedInitializer.class)
public class ExtendedTest extends BaseTest {}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
    classes = BaseConfig.class,
    initializers = BaseInitializer.class)
public class BaseTest {}

@ContextConfiguration(
    classes = ExtendedConfig.class,
    initializers = ExtendedInitializer.class,
    inheritInitializers = false)
public class ExtendedTest extends BaseTest {}
// In the following example, an exception would not be thrown even
// if no default XML file or @Configuration class is detected.
// In other words, the initializer would be responsible for 
// providing XML configuration files or annotated configuration
// classes to the provided context.
@ContextConfiguration(initializers = EntireAppInitializer.class)
public class InitializerWithoutConfigFilesOrClassesTest extends BaseTest  {}

Affects: 3.1 GA

Referenced from: commits 1f93777, 58daeea

11 votes, 15 watchers

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

@Sam, here's a nice use case explaining why this functionality is necessary, or at least very nice to have: http://forum.springsource.org/showthread.php?123995-Registering-PropertySources-in-test-cases&p=404617#post404617

I've asked Scott to weigh in here further to make his case.

@spring-projects-issues
Copy link
Collaborator Author

Scott Frederick commented

Following Chris' blog post on Unified Property Management in Spring 3.1, I can add custom PropertySource implementations to a stand-alone or web ApplicationContext.

I also want to be able to test how the system behaves with and without the custom PropertySource being registered. In order to do this in a test case using @ContextConfiguration, I need a way to manipulate the application context after it has been created but before it has been refreshed. Right now, as Chris suggested in the forum thread, I would need to manually create an app context in the test case instead of using @ContextConfiguration.

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

Sam, take a look at this post as well: http://stackoverflow.com/questions/10357985/java-spring-applicationcontext-configuration/10362527

Not the best use case, perhaps, but it does show that folks expect ACI classes and @ContextConfiguration to work together somehow.

@spring-projects-issues
Copy link
Collaborator Author

Christian Nedregård commented

My use case is not specific to testing. I need to be able to set the active profiles on application contexts loaded in non-web containers (e.g. Mule).
In these cases the problem is the same as with web applications: The application context is not created by our code, but by the container.

I would expect my ApplicationContextInitializers to be discovered and executed when defined as beans in xml or set up for classpath scanning.

Would it be possible to generalize this issue to encompass both test-support and support for other container-created contexts?

@spring-projects-issues
Copy link
Collaborator Author

George P. Stathis commented

+1 for the more generalized case. We have the same problem as Scott with @ContextConfiguration in our unit tests. We have hundreds of them so, re-writing them all to manage their own ApplicationContext is definitely not something we look forward to. But besides the unit tests, we are also in the same boat as Christian; our services are distributed as a JAR, so we rely on being provided with a spring-managed context that loads settings from a properties file in the classpath. We would then use those settings to turn bean profiles or/off via spring XML configuration without having to control the Application context ourselves.

@spring-projects-issues
Copy link
Collaborator Author

Sam Brannen commented

Christian and George,

I would expect my ApplicationContextInitializers to be discovered and executed when defined as beans in xml or set up for classpath scanning.

It is not feasible to have an ApplicationContextInitializer (ACI) defined as a Spring bean since an ACI should not reside in the ApplicationContext which it initializes.

Would it be possible to generalize this issue to encompass both test-support and support for other container-created contexts?

No, this issue is dedicated to providing support for configuring ACIs in the TestContext framework (e.g., via @ContextConfiguration).

If you would like to see support for configuring ACIs in other deployment environments, please create a separate JIRA issue for that specific use case.

Regards,

Sam

@spring-projects-issues
Copy link
Collaborator Author

Sam Brannen commented

If you are watching this issue, please feel free to participate in the discussion regarding the proposed Deliverables and the corresponding Pseudocode Examples listed in this issue's Description.

Thanks!

Sam

@spring-projects-issues
Copy link
Collaborator Author

Sam Brannen commented

Completed as described in the message for GitHub commit 58daeea1e2d7f3688057e0131cba5291a6f70fc2:

Support ApplicationContextInitializers in the TCF

Starting with Spring 3.1 applications can specify
contextInitializerClasses via context-param and init-param in web.xml;
however, there is currently no way to have such initializers invoked in
integration testing scenarios without writing a custom
SmartContextLoader. For comprehensive integration testing it should
therefore be possible to re-use ApplicationContextInitializers in the
Spring TestContext Framework as well.

This commit makes this possible at the @ContextConfiguration level by
allowing an array of ACI types to be specified, and the out-of-the-box
SmartContextLoader implementations invoke the declared initializers at
the appropriate time.

  • Added initializers and inheritInitializers attributes to
    @ContextConfiguration.

  • Introduced support for ApplicationContextInitializers in
    ContextConfigurationAttributes, MergedContextConfiguration, and
    ContextLoaderUtils.

  • MergedContextConfiguration stores context initializer classes as a
    Set and incorporates them into the implementations of hashCode() and
    equals() for proper context caching.

  • ApplicationContextInitializers are invoked in the new
    prepareContext(GenericApplicationContext, MergedContextConfiguration)
    method in AbstractGenericContextLoader, and ordering declared via the
    Ordered interface and @Order annotation is honored.

  • Updated DelegatingSmartContextLoader to support initializers.
    Specifically, a test class may optionally declare neither XML
    configuration files nor annotated classes and instead declare only
    application context initializers. In such cases, an attempt will
    still be made to detect defaults, but their absence will not result
    an an exception.

  • Documented support for application context initializers in Javadoc
    and in the testing chapter of the reference manual.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has: votes-jira Issues migrated from JIRA with more than 10 votes at the time of import in: test Issues in the test module type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants