Override a single @Configuration class on every spring boot @Test

SpringSpring BootSpring Test

Spring Problem Overview


On my spring boot application I want to override just one of my @Configuration classes with a test configuration (in particular my @EnableAuthorizationServer @Configuration class), on all of my tests.

So far after an overview of spring boot testing features and spring integration testing features no straightforward solution has surfaced:

  • @TestConfiguration: It's for extending, not overriding;
  • @ContextConfiguration(classes=…​) and @SpringApplicationConfiguration(classes =…​) let me override the whole config, not just the one class;
  • An inner @Configuration class inside a @Test is suggested to override the default configuration, but no example is provided;

Any suggestions?

Spring Solutions


Solution 1 - Spring

Inner test configuration

Example of an inner @Configuration for your test:

@RunWith(SpringRunner.class)
@SpringBootTest
public class SomeTest {

    @Configuration
    static class ContextConfiguration {
        @Bean
        @Primary //may omit this if this is the only SomeBean defined/visible
        public SomeBean someBean () {
            return new SomeBean();
        }
    }

    @Autowired
    private SomeBean someBean;

    @Test
    public void testMethod() {
        // test
    }
}

Reusable test configuration

If you wish to reuse the Test Configuration for multiple tests, you may define a standalone Configuration class with a Spring Profile @Profile("test"). Then, have your test class activate the profile with @ActiveProfiles("test"). See complete code:

@RunWith(SpringRunner.class)
@SpringBootTests
@ActiveProfiles("test")
public class SomeTest {
	
    @Autowired
    private SomeBean someBean;

    @Test
    public void testMethod() {
        // test
    }
}

@Configuration
@Profile("test")
public class TestConfiguration {
	@Bean
	@Primary //may omit this if this is the only SomeBean defined/visible
    public SomeBean someBean() {
        return new SomeBean();
    }
}

@Primary

The @Primary annotation on the bean definition is to ensure that this one will have priority if more than one are found.

Solution 2 - Spring

You should use spring boot profiles:

  1. Annotate your test configuration with @Profile("test").
  2. Annotate your production configuration with @Profile("production").
  3. Set production profile in your properties file: spring.profiles.active=production.
  4. Set test profile in your test class with @Profile("test").

So when your application starts it will use "production" class and when test stars it will use "test" class.

If you use inner/nested @Configuration class it will be be used instead of a your application’s primary configuration.

Solution 3 - Spring

I recently had to create a dev version of our application, that should run with dev active profile out of the box without any command line args. I solved it with adding this one class as a new entry, which sets the active profile programmatically:

package ...;

import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.StandardEnvironment;

@Import(OriginalApplication.class)
public class DevelopmentApplication {
    public static void main(String[] args) {
        SpringApplication application =
            new SpringApplication(DevelopmentApplication.class);
        ConfigurableEnvironment environment = new StandardEnvironment();
        environment.setActiveProfiles("dev");
        application.setEnvironment(environment);
        application.run(args);
    }
}

See Spring Boot Profiles Example by Arvind Rai for more details.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNotGaeLView Question on Stackoverflow
Solution 1 - SpringalexbtView Answer on Stackoverflow
Solution 2 - SpringSlava BabinView Answer on Stackoverflow
Solution 3 - SpringTamas HegedusView Answer on Stackoverflow