Spring Boot: @TestConfiguration在集成测试中不能覆盖Bean
Spring Boot: @TestConfiguration在集成测试中不能覆盖Bean
我在一个使用@Configuration
装饰的类中定义了一个Bean
:\n
@Configuration public class MyBeanConfig { @Bean public String configPath() { return "../production/environment/path"; } }
\n我有一个使用@TestConfiguration
装饰的类,应该覆盖这个Bean
:\n
@TestConfiguration public class MyTestConfiguration { @Bean @Primary public String configPath() { return "/test/environment/path"; } }
\nconfigPath
bean 用于设置一个包含在启动过程中必须读取的注册码的外部文件的路径。它在一个@Component
类中使用:\n
@Component public class MyParsingComponent { private String CONFIG_PATH; @Autowired public void setCONFIG_PATH(String configPath) { this.CONFIG_PATH = configPath; } }
\n在尝试调试时,我在每个方法以及测试配置类的构造函数中设置了断点。断点命中了@TestConfiguration
的构造函数,所以我知道我的测试配置类实例化了,但是该类的configPath
方法从未被命中。相反,命中了普通@Configuration
类的configPath
方法,并且MyParsingComponent
中的@Autowired
String
始终是../production/environment/path
,而不是预期的/test/environment/path
。\n不确定为什么会发生这种情况。非常感谢您的帮助。
在Spring Boot中,当我们进行集成测试时,有时会遇到一个问题,即@TestConfiguration无法覆盖Bean。下面是这个问题产生的原因和解决方法:
1. 首先,我们需要在测试中显式导入测试配置,即通过({MyTestConfiguration.class})来导入。
2. 其次,@TestConfiguration
中的方法名和@Configuration
中的方法名必须不同。至少在Spring Boot v2.2中是有区别的。
3. 另外,确保spring.main.allow-bean-definition-overriding=true
,否则无法覆盖Bean。
需要注意的是,第二条和第三条陈述可能会相互冲突 - Bean覆盖机制意味着Bean名称要匹配。
当我们在Spring Boot中进行集成测试时,如果遇到@TestConfiguration无法覆盖Bean的问题,可以按照以上三个步骤进行解决。
在进行集成测试时,如果想要覆盖某个bean的定义,需要确保工厂方法的方法名与现有的bean名称不匹配。如果方法名称与现有的bean名称冲突,Spring会静默地跳过这些工厂方法,不会调用它们或实例化这些bean。
如果想要在测试中覆盖bean的定义,可以在注解中明确指定bean的名称作为字符串参数。
另外,还需要注意静态内部类中的工厂方法的命名不能与实际bean的命名相同。
在某些特殊情况下,还需要添加@Primary
注解,否则会抛出expected single matching bean but found 2
的异常。
以上是解决(Spring Boot: @TestConfiguration Not Overriding Bean During Integration Test)这个问题的原因和解决方法。
在Spring Boot参考手册的“检测测试配置”部分中记录着,使用@TestConfiguration
注解的顶级类中配置的任何bean都不会通过组件扫描来获取。因此,您必须显式地注册您的TestConfiguration
类。
您可以通过在测试类上使用@Import(MyTestConfiguration.class)
或@Import(MyTestConfiguration.class)
来实现。
另一方面,如果使用@TestConfiguration
注解的类是测试类中的static
嵌套类,则会自动注册。
我尝试使用@TestConfiguration
放在一个顶级类上,并且使用@Import(MyTestConfiguration.class)
和不使用@TestConfiguration
但使用@Import(MyTestConfiguration.class)
进行测试。结果是相同的。这是否意味着@TestConfiguration
是无用的?
@TestConfiguration
仍然是有用的。请参考链接的文档以获取详细信息。
链接已失效。
由于Spring Boot 2.2文档的更改,我修复了链接。谢谢。
我想重用@TestConfiguration
用于多个测试类,因此在其他测试类都继承的抽象测试类中定义它可能是一个选项。不幸的是,如果抽象类中定义的@TestConfiguration
,当前测试类无法获取到它。这是设计如此吗?如何在测试类之间共享@TestConfiguration
?
为什么我无法使用@TestConfiguration
注解覆盖一个同名的spring bean?我可以使用@TestConfiguration
和静态内部类注解为@Configuration
来覆盖它。
提醒一下,尝试使用@Import(Your.class)
和@Import(Your.class)
,一个接一个地尝试。不知道为什么,但前者对我没用。然而,后者有效!
在Kotlin中使用@Import
时,对我来说不起作用,但是使用@Import(classes = [TestConfiguration::class])
可以工作。
当使用@TestConfiguration
时,我还需要对被覆盖的bean使用@Primary
注解(@Primary
注解用于标识主要的bean)。