title: SpringApplicationContextLoader ignores Application class
body: <p>The <code>SpringApplicationContextLoader</code> assumes that the application is either using 100% XML or 100% Java config. This is because <code>@ContextConfiguration</code> allows either a list of classes or locations/value, not both. If any is specified, <code>SpringApplicationContextLoader</code> ignores the Application class that creates and starts the SpringApplication.</p>
  
  <p>Trying to make Boot work with a 100% Groovy/no-XML pet project, I ran across the above issue. My Application class has <code>@EnableAutoConfiguration</code> and <code>@ComponentScan</code> annotations on it, the former required by Boot to set up a Web server. The later I had to keep because of <a href="https://jira.spring.io/browse/SPR-11627" rel="nofollow">SPR-11627</a>. On the other hand, if I omitted the locations/value on <code>@ContextConfiguration</code>, dependencies weren't set up (duh!).</p>
  
  <p>I give the code below along with a patch that I locally made to <code>SpringApplicationContextLoader</code>. If there's a better way, please let me know.</p>
  
  <p><strong>MovieDatabaseRESTClientIntegrationTest.groovy</strong></p>
  
  <pre><code>RunWith(SpringJUnit4ClassRunner)
  @ContextConfiguration(value = ['classpath:client-config.groovy', 'classpath:integ-test-config.groovy'],
          loader = PatchedSpringApplicationContextLoader)
  @SpringApplicationConfiguration(classes = MovieDatabaseApplication)
  @WebAppConfiguration
  @IntegrationTest
  class MovieDatabaseRESTClientIntegrationTest {
  </code></pre>
  
  <p><strong>MovieDatabaseApplication.groovy</strong></p>
  
  <pre><code>@EnableAutoConfiguration
  @ComponentScan
  class MovieDatabaseApplication {
  </code></pre>
  
  <p><strong>SpringApplicationContextLoader.java fix</strong></p>
  
  <pre><code>private Set&lt;Object&gt; getSources(MergedContextConfiguration mergedConfig) {
          Set&lt;Object&gt; sources = new LinkedHashSet&lt;Object&gt;();
          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;
  }
  </code></pre>
  
  <p>Also posted on Spring forum.</p>