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

SpringApplicationContextLoader ignores Application class #603

Closed
asarkar opened this issue Mar 30, 2014 · 2 comments
Closed

SpringApplicationContextLoader ignores Application class #603

asarkar opened this issue Mar 30, 2014 · 2 comments
Labels
status: duplicate A duplicate of another issue status: invalid An issue that we don't feel is valid

Comments

@asarkar
Copy link

asarkar commented Mar 30, 2014

The SpringApplicationContextLoader assumes that the application is either using 100% XML or 100% Java config. This is because @ContextConfiguration allows either a list of classes or locations/value, not both. If any is specified, SpringApplicationContextLoader ignores the Application class that creates and starts the SpringApplication.

Trying to make Boot work with a 100% Groovy/no-XML pet project, I ran across the above issue. My Application class has @EnableAutoConfiguration and @componentscan annotations on it, the former required by Boot to set up a Web server. The later I had to keep because of SPR-11627. On the other hand, if I omitted the locations/value on @ContextConfiguration, dependencies weren't set up (duh!).

I give the code below along with a patch that I locally made to SpringApplicationContextLoader. I intend to send a pull request for this fix.

MovieDatabaseRESTClientIntegrationTest.groovy

RunWith(SpringJUnit4ClassRunner)
@ContextConfiguration(value = ['classpath:client-config.groovy', 'classpath:integ-test-config.groovy'],
        loader = PatchedSpringApplicationContextLoader)
@SpringApplicationConfiguration(classes = MovieDatabaseApplication)
@WebAppConfiguration
@IntegrationTest
class MovieDatabaseRESTClientIntegrationTest {

MovieDatabaseApplication.groovy

@EnableAutoConfiguration
@ComponentScan
class MovieDatabaseApplication {

SpringApplicationContextLoader.java local fix

private Set<Object> getSources(MergedContextConfiguration mergedConfig) {
        Set<Object> sources = new LinkedHashSet<Object>();
        sources.addAll(Arrays.asList(mergedConfig.getClasses()));
        sources.addAll(Arrays.asList(mergedConfig.getLocations()));

        /* The Spring application class may have annotations on it too. If such a class is declared on the test class,
        * add it as a source too. */
        SpringApplicationConfiguration springAppConfig = AnnotationUtils.findAnnotation(mergedConfig.getTestClass(),
                SpringApplicationConfiguration.class);

        if (springAppConfig != null) {
            sources.addAll(Arrays.asList(springAppConfig.classes()));
        }

        if (sources.isEmpty()) {
            throw new IllegalStateException(
                    "No configuration classes or locations found in @SpringApplicationConfiguration. "
                            + "For default configuration detection to work you need Spring 4.0.3 or better (found "
                            + SpringVersion.getVersion() + ").");
        }
        return sources;
}
@sbrannen
Copy link
Member

The following comments have been copied from SPR-11627.

I see several issues with your configuration.

  1. Declaring both @ContextConfiguration and @SpringApplicationConfiguration directly on a test class is not supported. The first instance of @ContextConfiguration that is discovered for a given test class (either on a class in the test class hierarchy or as a meta-annotation) will be used. All others will be ignored.

Note that @SpringApplicationConfiguration is itself meta-annotated with @ContextConfiguration. Therefore, the declaration of @SpringApplicationConfiguration must be sufficient on its own.

  1. Declaring both classes and locations/value for @ContextConfiguration is not supported (at least not in the Spring TestContext Framework in Core Spring). You are only allowed to declare one or the other. See the "Testing" chapter of the reference manual for the Spring Framework as well as the Javadoc for @ContextConfiguration for details.

In general, you need to select "one entry point" into your configuration. This is how production code works, and this is how test code works. You can always import other styles. For example, JavaConfig can import XML; XML can import JavaConfig; Groovy can import XML; etc.

Hope this helps clarify things a bit for you.

Regards,

Sam

@dsyer
Copy link
Member

dsyer commented Mar 31, 2014

Closing (mostly invalid, but duplicated in #604 anyway).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: duplicate A duplicate of another issue status: invalid An issue that we don't feel is valid
Projects
None yet
Development

No branches or pull requests

3 participants