Spring Boot测试如何覆盖主配置同Qualifier Bean解决非唯一冲突
报错原因
@Qualifier 是Bean筛选标记而非唯一主键,你的主配置和测试配置中存在两个带相同@Qualifier值的File类型Bean,Spring无法判断优先级,因此抛出NoUniqueBeanDefinitionException异常。
解决方案
以下方案按改造成本从低到高排序:
方案1:测试Bean添加@Primary注解(最常用,无需修改主代码)
给测试配置的Bean加上@Primary注解,同类型Bean匹配时会优先选择带该注解的实现:
@TestConfiguration public class TestConfig { @Bean @Primary @Qualifier("usersDatabase") public File getUsersDatabaseTestFile() { return Paths.get("src/test/resources/database/users.csv").toFile(); } @Bean @Primary @Qualifier("urlsDatabase") public File getUrlsDatabaseTestFile() { return Paths.get("src/test/resources/database/urls.csv").toFile(); } }
方案2:主配置Bean添加@ConditionalOnMissingBean注解
给主配置的Bean加上@ConditionalOnMissingBean,当上下文中已存在对应Bean时,主配置的Bean不会重复注册:
@Configuration public class UrlAnalyzerConfiguration { @Bean @Qualifier("usersDatabase") @ConditionalOnMissingBean(name = "usersDatabase") public File getUsersDatabaseFile() { return Paths.get("src/main/resources/database/users.csv").toFile(); } @Bean @Qualifier("urlsDatabase") @ConditionalOnMissingBean(name = "urlsDatabase") public File getUrlsDatabaseFile() { return Paths.get("src/main/resources/database/urls.csv").toFile(); } }
该方案适合预留测试扩展口子的场景,后续所有测试替换这两个Bean都无需额外配置。
方案3:测试类指定加载上下文,排除冗余主配置
单测场景下可以只加载需要的业务Bean和测试配置,避免加载主配置的冗余Bean,同时提升测试启动速度:
@SpringBootTest(classes = {TestConfig.class, UserRepositoryImpl.class}) public class UserRepositoryTest { @Autowired private UserRepository userRepository; // 测试逻辑 }
方案4:同Bean名覆盖
给主配置和测试配置的对应Bean设置相同的name属性,后注册的测试Bean会覆盖主配置Bean:
注意:Spring Boot 2.1及以上版本默认关闭Bean覆盖,需要在测试配置文件中添加
spring.main.allow-bean-definition-overriding=true开启该功能。
主配置修改示例:
@Bean(name = "usersDatabase") @Qualifier("usersDatabase") public File getUsersDatabaseFile() { return Paths.get("src/main/resources/database/users.csv").toFile(); }
测试配置修改示例:
@Bean(name = "usersDatabase") @Qualifier("usersDatabase") public File getUsersDatabaseTestFile() { return Paths.get("src/test/resources/database/users.csv").toFile(); }
内容的提问来源于stack exchange,提问作者Mykhailo Pavliuk
相关产品推荐
相关产品推荐

