Skip to content
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

Support simultaneous use of classes and locations in @ContextConfiguration [SPR-11634] #16257

Closed
3 tasks done
spring-projects-issues opened this issue Mar 31, 2014 · 6 comments
Assignees
Labels
in: test Issues in the test module type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

Dave Syer opened SPR-11634 and commented

Background

It should be up to a SmartContextLoader to decide if it supports both classes and locations. Historically there was no ApplicationContext that supported both XML resources and annotated classes (so you had to choose one as an entry point). That isn't the case any longer since Spring Boot doesn't care much what it eats.

Deliverables

  1. Stop throwing an IllegalArgumentException in the constructor in ContextConfigurationAttributes if both locations and classes are supplied.
  2. Update the Javadoc for all related classes to ensure that it doesn't state that locations and classes cannot be used simultaneously.
    • for example: ContextConfigurationAttributes, @ContextConfiguration, etc.
  3. Update the Testing chapter of the reference manual to ensure that it doesn't state that locations and classes cannot be used simultaneously.

Affects: 4.0.3

Referenced from: commits 8e89aff, 989f619, 1f017c4

@spring-projects-issues
Copy link
Collaborator Author

Abhijit Sarkar commented

Should this really be a "minor" improvement? I'm sure lot of people will appreciate this change, more so as the ways to configure the application increases from XML, to Java, to Groovy. What's the point of providing different ways if someone is forced to use just one?

@spring-projects-issues
Copy link
Collaborator Author

Sam Brannen commented

What's the point of providing different ways if someone is forced to use just one?

Spring has never forced you to use just one.

Historically, it has never been possible to instantiate an ApplicationContext by supplying different resource types (i.e., XML, annotated classes, or Groovy scripts). For example, ClassPathXmlApplicationContext, FileSystemXmlApplicationContext, XmlWebApplicationContext, and AnnotationConfigApplicationContext only support a single resource type.

Now, having said that, it is possible to instantiate a GenericApplicationContext and use different implementations of BeanDefinitionReader to load bean definitions from different resource types; however, standard deployments have never supported that (e.g., in a Servlet container using AnnotationConfigWebApplicationContext or XmlWebApplicationContext). The use of a GenericApplicationContext has always required a custom solution. For what it's worth, Spring Boot appears to be different in this regard, but that is a very new change in the Spring ecosystem.

For further information on how to load bean definitions from different resource types in a conventional manner, please see the Mixing XML resources and annotated classes section of the reference manual. Here's an excerpt:

It may sometimes be desirable to mix XML resources and annotated classes (i.e., typically @Configuration classes) to configure an ApplicationContext for your tests. For example, if you use XML configuration in production, you may decide that you want to use @Configuration classes to configure specific Spring-managed components for your tests, or vice versa. As mentioned in the section called “Spring Testing Annotations” the TestContext framework does not allow you to declare both via @ContextConfiguration, but this does not mean that you cannot use both.

If you want to use XML and @Configuration classes to configure your tests, you will have to pick one as the entry point, and that one will have to include or import the other. For example, in XML you can include @Configuration classes via component scanning or define them as normal Spring beans in XML; whereas, in a @Configuration class you can use @ImportResource to import XML configuration files. Note that this behavior is semantically equivalent to how you configure your application in production: in production configuration you will define either a set of XML resource locations or a set of @Configuration classes that your production ApplicationContext will be loaded from, but you still have the freedom to include or import the other type of configuration.

The key thing to take away here is that you want the ApplicationContext that is loaded for your tests to be loaded in the same manner as it is loaded in production. So if you are using an ApplicationContext in production that only supports a single resource type for bean definitions, then you have to do the same in integration tests. Otherwise, you run the risk of having bean definitions loaded and parsed in different orders and with different semantics in production and tests.

Regards,

Sam

@spring-projects-issues
Copy link
Collaborator Author

Sam Brannen commented

Completed as described in the comments for GitHub commit 8e89aff:

Support classes AND locations in @ContextConfiguration

Prior to this commit, the Spring TestContext Framework did not support
the declaration of both 'locations' and 'classes' within
@ContextConfiguration at the same time.

This commit addresses this in the following manner:

  • ContextConfigurationAttributes no longer throws an
    IllegalArgumentException if both 'locations' and 'classes' are
    supplied to its constructor.

  • Concrete SmartContextLoader implementations now validate the
    supplied MergedContextConfiguration before attempting to load the
    ApplicationContext. See validateMergedContextConfiguration().

  • Introduced tests for hybrid context loaders like the one used in
    Spring Boot. See HybridContextLoaderTests.

  • Updated the Testing chapter of the reference manual so that it no
    longer states that locations and classes cannot be used
    simultaneously, mentioning Spring Boot as well.

  • The Javadoc for @ContextConfiguration has been updated accordingly.

  • Added hasLocations(), hasClasses(), and hasResources() convenience
    methods to MergedContextConfiguration.

@spring-projects-issues
Copy link
Collaborator Author

Sam Brannen commented

Backported to Spring 4.0.4 in GitHub commit 989f619.

@spring-projects-issues
Copy link
Collaborator Author

Abhijit Sarkar commented

Tested with 4.0.4.BUILD-SNAPSHOT, the following works: (y)

@ContextConfiguration(value = ['classpath:client-config.groovy', 'classpath:integ-test-config.groovy'],
        classes = [MovieDatabaseApplication],
        loader = SpringApplicationContextLoader)

@spring-projects-issues
Copy link
Collaborator Author

Sam Brannen commented

Great!

Thanks for verifying it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: test Issues in the test module type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants