基于Spring Boot的Spring Batch项目JUnit测试无法注入Service如何解决
问题原因
- 动态代理类型不匹配
Spring默认会为实现了接口的Bean使用JDK动态代理,代理对象实现的是NotaryService接口,类型不属于NotaryServiceImpl,直接注入实现类自然找不到对应Bean。 - 默认组件扫描范围不覆盖
你的主启动类在com.notariato.updateInfo包下,@SpringBootApplication默认只扫描当前包及其子包,你的Service类在com.notariato.service包,不在默认扫描范围内,就算测试类加了@ComponentScan,出现配置冲突时也会失效。
解决方案
场景1:保持集成测试(加载Spring上下文)
仅需要做两处修改即可:
- 把注入的类型改成接口
NotaryService,不要直接注入实现类 - 不需要额外加
@ComponentScan,直接调整主启动类的扫描范围即可,推荐把主启动类移到上层包com.notariato下,符合Spring Boot项目规范。
修改后的测试类代码示例:
package com.notariato.updateInfo; import static org.junit.Assert.assertTrue; import org.junit.jupiter.api.Test; import org.springframework.batch.test.context.SpringBatchTest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import com.notariato.service.NotaryService; // 不需要测试Batch相关组件的话,可以去掉@SpringBatchTest注解 @SpringBootTest @SpringBatchTest class UpdateInfoBatchApplicationTests { @Autowired private NotaryService notaryService; @Test void getNotaryList() { System.out.println("TEST"); notaryService.getNotaryList(); assertTrue(true); } }
如果不想移动主启动类的位置,也可以在主启动类的@SpringBootApplication注解上指定扫描包:
@SpringBootApplication(scanBasePackages = "com.notariato") @EnableBatchProcessing @EnableScheduling public class UpdateInfoBatchApplication { public static void main(String[] args) { SpringApplication.run(UpdateInfoBatchApplication.class, args); } }
场景2:纯单元测试(不加载Spring上下文,执行速度更快)
如果不需要依赖Spring上下文的其他组件,可以直接做普通单元测试,不需要加任何Spring相关测试注解,手动实例化Service类即可:
package com.notariato.updateInfo; import static org.junit.Assert.assertTrue; import org.junit.jupiter.api.Test; import com.notariato.service.NotaryServiceImpl; class UpdateInfoBatchApplicationTests { private NotaryServiceImpl notaryService = new NotaryServiceImpl(); @Test void getNotaryList() { System.out.println("TEST"); notaryService.getNotaryList(); assertTrue(true); } }
内容的提问来源于stack exchange,提问作者AndreaNobili
相关产品推荐
相关产品推荐

