Spring Boot: @TestConfiguration Not Overriding Bea

2020-02-26 15:21发布

问题:

I have a Bean defined in a class decorated with @Configuration:

@Configuration
public class MyBeanConfig {

    @Bean
    public String configPath() {
        return "../production/environment/path";
    }
}

I have a class decorated with @TestConfiguration that should override this Bean:

@TestConfiguration
public class MyTestConfiguration {

    @Bean
    @Primary
    public String configPath() {
        return "/test/environment/path";
    }
}

The configPath bean is used to set the path to an external file containing a registration code that must be read during startup. It is used in an @Component class:

@Component
public class MyParsingComponent {

    private String CONFIG_PATH;

    @Autowired
    public void setCONFIG_PATH(String configPath) {
        this.CONFIG_PATH = configPath;
    }
}

While trying to debug this, i set a breakpoint inside each method as well as the constructor of the test config class. The @TestConfiguration's constructor breakpoint is hit, so i know that my test configuration class instantiates, however the configPath() method of that class is never hit. Instead, the configPath() method of the normal @Configuration class is hit and the @Autowired String in MyParsingComponent is always ../production/environment/path rather than the expected /test/environment/path.

Not sure why this is happening. Any thoughts would be greatly appreciated.

回答1:

As documented in the Detecting Test Configuration section of the Spring Boot reference manual, any beans configured in a top-level class annotated with @TestConfiguration will not be picked up via component scanning. So you have to explicitly register your @TestConfiguration class.

You can do that either via @Import(MyTestConfiguration.class) or @ContextConfiguration(classes = MyTestConfiguration.class) on your test class.

On the other hand, if your class annotated with @TestConfiguration were a static nested class within your test class, it would be registered automatically.



回答2:

Make sure that the method name of your @Bean factory method does not match any existing bean name. I had issues with method names like config() or (in my case) prometheusConfig() which collided with existing bean names. Spring skips those factory methods silently and simply does not call them / does not instantiate the beans.

If you want to override a bean definition in your test, use the bean name explicitly as string parameter in your @Bean("beanName") annotation.