Spring Boot JUnit测试中如何不修改原代码覆盖@Primary注解的Bean
问题根因
你当前报错是因为业务代码中的EmailServiceImpl已经标注了@Primary,测试配置类中定义的Mock Bean又额外加了@Primary,Spring容器初始化时检测到两个同类型的Primary Bean,直接触发冲突。以下是不需要修改业务代码的可行解决方案,按易用性排序:
方案1:使用Spring Boot Test自带的@MockBean注解(最推荐)
该注解是Spring Boot Test原生提供的测试工具,专门用于在测试环境中替换容器内的同类型原有Bean,优先级天然高于普通业务Bean,不需要额外写测试配置类,也不需要加@Primary。
直接删除原有测试配置类ServConf,修改测试类代码即可:
@ActiveProfiles("test") @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = Application.class, loader = SpringApplicationContextLoader.class) public class JunitClass { // 自动替换容器中原有EmailService Bean,生成Mock对象 @MockBean private EmailService emailService; @Autowired private ResourceServiceInterface resource; @Test public void testMethod() { Mockito.doNothing().when(emailService).validateEmail(Mockito.anyString()); boolean validResource = resource.checkResource("email@gmail.com", 1234L); assertEquals(validResource, true); } }
方案2:测试配置类过滤业务Bean扫描
如果你不想用@MockBean,可以在测试配置类中添加组件扫描过滤规则,直接把业务EmailServiceImpl从测试环境的容器扫描列表中排除,仅保留你定义的Mock Bean,完全规避冲突:
@Profile("test") @Configuration @ComponentScan(excludeFilters = @ComponentScan.Filter( type = FilterType.ASSIGNABLE_TYPE, value = EmailServiceImpl.class )) public class ServConf { @Bean public EmailService getEmailService() { return Mockito.mock(EmailServiceImpl.class); } }
该方案不需要修改业务代码,过滤规则仅在test profile生效,不会影响生产环境运行。
内容的提问来源于stack exchange,提问作者User_1940878
相关产品推荐
相关产品推荐

