eremic
eremic

Reputation: 123

How to exclude ApplicationContextInitializers in @SpringBootTest?

I'm trying to run a @SpringBootTest in a "clean" context without having MyApplicationContextInitializer executed.

The MyApplicationContextInitializer is included inside the spring.factories file in a compile-scope dependency like this:

org.springframework.context.ApplicationContextInitializer=\
com.eremic.myapp.MyApplicationContextInitializer

Test class:

@SpringBootTest(webEnvironment = RANDOM_PORT)
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = TestContext.class)
public class UsersControllerTest {}

Test config:

@SpringBootConfiguration
public class TestContext {}

Is there a way to exclude MyApplicationContextInitializer from @SpringBootTest?

I've already tired with excludeFilters @ComponentScan.Filters, but it has no effect on ApplicationContextInitializer.

Also, I've tried to annotate TestContext with @SpringBootApplication and to limit component scanning with scanBasePackages and/or to use exclude = MyApplicationContextInitializer.class but it has no effect too.

So far the only way to prevent MyApplicationContextInitializer from executing inside @SpringBootTest is to remove the maven dependency in which the MyApplicationContextInitializer is declared.

Upvotes: 6

Views: 2127

Answers (2)

Dmitry Smorzhok
Dmitry Smorzhok

Reputation: 635

For those who are interested in how exclusions of ApplicationContextInitializer were made possible in SpringBoot (by @phil_webb).

You have to extend org.springframework.boot.test.context.SpringBootContextLoader and override getInitializers method:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.test.context.SpringBootContextLoader;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.test.context.MergedContextConfiguration;

import java.util.List;

/**
 * Custom context loader for modifying {@code ApplicationContextInitializer}'s
 */
public class CustomInitializersContextLoader extends SpringBootContextLoader {

    @Override
    protected List<ApplicationContextInitializer<?>> getInitializers(MergedContextConfiguration config,
                                                                     SpringApplication application) {
        // modify list of initializers however you need
        return super.getInitializers(config, application);
    }

}

And then you can enable this loader with org.springframework.test.context.ContextConfiguration:

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;

@SpringBootTest
@ContextConfiguration(loader = CustomInitializersContextLoader.class)
public abstract class DemoTest {
    // regular tests
}

Upvotes: 0

Phil Webb
Phil Webb

Reputation: 8622

There's not currently a way to filter ApplicationContextInitializer classes loaded from factories. To do that on a per-test level you'd need to use a custom annotation that uses a different SpringBootTestContextBootstrapper. The bootstrapper would need to return a SpringBootContextLoader that filtered the initializers. Feel free to raise an issue and we can add some protected method to SpringBootContextLoader for you to override.

Upvotes: 2

Related Questions