Spring Boot:@TestConfiguration在集成测试期间不覆盖Bean

The*_*ush 22 java spring-test spring-boot

Bean在用@Configuration修饰的类中定义了:

@Configuration
public class MyBeanConfig {

    @Bean
    public String configPath() {
        return "../production/environment/path";
    }
}
Run Code Online (Sandbox Code Playgroud)

我有一个用@TestConfiguration修饰的类应该覆盖它Bean:

@TestConfiguration
public class MyTestConfiguration {

    @Bean
    @Primary
    public String configPath() {
        return "/test/environment/path";
    }
}
Run Code Online (Sandbox Code Playgroud)

configPathbean用于设置外部文件的路径,该文件包含必须在启动期间读取的注册码.它用在@Component类中:

@Component
public class MyParsingComponent {

    private String CONFIG_PATH;

    @Autowired
    public void setCONFIG_PATH(String configPath) {
        this.CONFIG_PATH = configPath;
    }
}
Run Code Online (Sandbox Code Playgroud)

在尝试调试时,我在每个方法中设置了一个断点以及测试配置类的构造函数.在@TestConfiguration类的构造函数断点命中,所以我知道我的测试配置类实例化,但是configPath()该类的方法不会被击中.相反,configPath()正常的@Configuration类的方法被命中,而@Autowired Stringin MyParsingComponent总是../production/environment/path而不是预期的/test/environment/path.

不知道为什么会这样.任何想法将不胜感激.

Sam*_*nen 44

如Spring Boot参考手册的" 检测测试配置"部分所述,在注释的顶级类中配置的任何bean @TestConfiguration不会通过组件扫描获取.所以你必须明确注册你的@TestConfiguration课程.

您可以通过@Import(MyTestConfiguration.class)@ContextConfiguration(classes = MyTestConfiguration.class)在测试类上执行此操作.

在另一方面,如果你有注解的类@TestConfiguration是一个static嵌套类的测试类,它会自动注册.


And*_*eck 14

对我来说这段代码有效:

  @TestConfiguration // 1. necessary
  public class TestMessagesConfig {

    @Bean
    @Primary // 2. necessary
    public MessageSource testMessageSource() { // 3. different method name than in production code e.g. add test prefix

    }
  }
Run Code Online (Sandbox Code Playgroud)


Mak*_*kin 6

  • 测试配置必须通过@Import({MyTestConfiguration.class}).
  • 的名称@Bean的方法@Configuration,并@TestConfiguration有不同。至少它在 Spring Boot v2.2 中有所不同。
  • 还要确保spring.main.allow-bean-definition-overriding=true否则无法覆盖 bean。

  • 您的第二个和第三个项目符号语句相互冲突 - bean 覆盖机制意味着 bean 名称确实匹配。 (3认同)

Did*_*edt 6

我遇到了一个相关的问题,即使我使用内部静态类,我的测试 bean 也没有被注册。

事实证明,您仍然需要将内部静态类添加到@ContextConfiguration类数组中,否则 @TestConfiguration 内的 bean 不会被拾取。

public interface Foo {
    String execute();
}
Run Code Online (Sandbox Code Playgroud)
public class FooService {
    private final Foo foo;

    FooService(Foo foo) {
        this.foo = foo;
    }

    public String execute() {
        return foo.execute();
    }
}
Run Code Online (Sandbox Code Playgroud)
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {FooService.class, FooTest.FooTestConfig.class})
public class FooTest {
    @Autowired
    FooService fooService;

    @Test
    void test() {
        Assertions.assertEquals("MY_TEST_BEAN", fooService.execute());
    }

    @TestConfiguration
    static class FooTestConfig {
        @Bean
        public Foo getFooBean() {
            return () -> "MY_TEST_BEAN";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

确保@Bean工厂方法的方法名称与任何现有的Bean名称都不匹配。我遇到了诸如config()或(在我的情况下) prometheusConfig()之类的方法名称与现有bean名称冲突的问题。Spring 默默地跳过那些工厂方法并且根本不调用它们/不实例化bean。

如果要在测试中覆盖bean定义,请在@Bean(“ beanName”)批注中显式使用bean名称作为字符串参数。

  • 这是实际的答案。我有一个带有 @TestConfiguration 的嵌套静态类,但它不起作用。问题在于工厂方法的命名与实际 bean 的命名相同。 (4认同)

小智 5

就我而言,将 @ 替换Import(TestConfig.class)为 就@ContextConfiguration(classes=TestConfig.class)可以了。由于某种原因,TestConfig 中的一些 bean 但 1 直到我替换@Import@ContextConfiguration. 在一些因没有投票而被隐藏的评论中也提到了这一点。