How can I test logic that integrates with early Spring bootstrapping?

I am trying to prevent my spring boot application to start if I consider two or more active profiles to be conflicting. I.e. dev and prod should not be active at the same time.

Moreover, I want to make sure this logic and its integration into Spring bootstrapping code is properly tested.

I tried EnvironmentPostProcessor as well as ApplicationEvent<ApplicationEnvironmentPrepared>, I have annotated the test with @SpringBootTest and I use assertThrows in the test method.

If I do new AnnotationApplicationContext() I don't seem to find a way to manipulate the environment used by the context and if I try to SpringApplication.run() a test application myself, it doesn't seem to be able to find any injectable bean for environment at all.

I am pretty sure I am trying the wrong things and maybe there's an easier way to achieve my goal anyway. Any hints or pointers would be greatly appreciated.

@Bean
public ApplicationListener<ApplicationEnvironmentPreparedEvent> ensureNonConflictingProfiles() {
    return event -> {
        if (event.getEnvironment().getActiveProfiles().length > 1) {
            throw new IllegalStateException("Only one of the profiles can be active");
        }
    };
}

Upvotes: 0

Views: 58

Answers (2)

Never mind. I just figured out that having a @Component that was called com.example.whatever.Environment on the classpath led to SpringApplication.run() to fail with No qualifying bean of type 'org.springframework.core.env.Environment' available but renaming this to e.g. com.example.whatever.Environment1 fixed that problem.

Upvotes: 0

Prashant
Prashant

Reputation: 5403

Have you tried registering your custom EnvironmentPostprocessor with spring.factories? This can be done by putting the following code in spring.factores file located at META-INF/spring.factories:

org.springframework.boot.env.EnvironmentPostProcessor=com.example.MyCustomEnvPostProcessor

Now you can create a ProfileConflictTest class as:

@SpringBootTest
class ProfileConflictTest {

    @Test
    void testProfileConflict() {
        assertThrows(IllegalArgumentException.class,() -> {
            SpringApplication app = new SpringApplication(MyApplication.class);
            app.setAdditionalProfiles("dev", "prod");
            app.run();
        });
    }
}

Upvotes: 0

Related Questions