Why can't @SpringBootTest find any beans after Spring Boot 2 upgrade?

330 Views Asked by At

I am currently trying to upgrade a large Java 8 project from Spring Boot 1.5 to Spring Boot 2.7 (yes, very late to the party, I know). One thing I can’t figure out is that @SpringBootTest in SB2 seems to not be providing the ApplicationContext in the same way as it used to. We have a number of integration tests that expect Autowired components (which is why we use the @SpringBootTest annotation, because we want to test under a full ApplicationContext). These tests used to work fine in SB 1.5, but in SB 2.7, these ITs bomb out with “Failed to load ApplicationContext”, caused by NoSuchBeanDefinitionException. We aren’t doing anything exotic with our app @ComponentScans, and all of these allegedly missing beans can be found either in our application’s own package/subpackages or in Spring itself (i.e., all of the usual places that beans should be automatically found).

The only way I have found to get these tests to succeed is to add an explicit @ContextConfiguration and add each and every specific configuration class (both in our app code and in Spring) which might be needed to provide a bean. So I’m ending up with ITs that look like this:

package my.app.submodule;

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = {
    org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration.class,
    org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration.class,
    org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean.class,
    my.app.config.SecurityConfig,
    my.app.config.SomeConfig
})
public class SomeTestIT
{ …
    // some Autowiring required here
}

(So much for autoconfiguration!) This approach eventually works, but it’s tedious and it seems rather brittle, and I’d really like to understand why the ApplicationContext isn’t just getting built in these @SpringBootTest ITs the way that it does for the actual application (and the way that it used to for these ITs with SB 1.5).

We’re using Java 8 (OpenJDK), maven-failsafe-plugin 3.1.2, Spring Boot 2.7.11, Spring Test 5.3.27 (using junit4.SpringRunner), junit 4.13.2.

It was suggested that I explicitly reference my test application class in the @SpringBootTest annotation, so I tried that:

package my.app.submodule;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {my.app.MyTestApplication.class})
public class SomeTestIT
{ …
    // some Autowiring required here
}

where MyTestApplication is a class annotated with @SpringBootApplication, but that failed in the same way.

1

There are 1 best solutions below

4
On

You should provide a class in the @SpringBootTest annotation pointing to a class that is annotated with @SpringBootApplication. Thus the whole SpringBoot startup will take place normally. You shouldn't need to specifiy any AutoConfiguration to process as it will be automatically be aware of that with your classpath used at test time.

You can check this article from baeldung