SpringBoot测试中Clock Bean未自动注入触发空指针问题求助
问题核心原因
你出现空指针的根本原因是MockitoExtension的工作机制和你混用注解的逻辑冲突,具体有三个错误点:
@ExtendWith(MockitoExtension.class)是纯单元测试的扩展,只负责处理Mockito相关注解(@Mock/@Spy/@InjectMocks),完全不会启动Spring上下文,所以你写的@Autowired注解根本不会生效,Clock自然无法注入,为空是必然结果。@InjectMocks的注入规则是:只会把测试类中用@Mock/@Spy声明过的对象注入到目标类中,你没有在测试类中声明Clock类型的Mock/实例,所以目标Service里的Clock字段会被留空。- 额外注意你描述里的类名 mismatch:你提到待测试的是
VoteService,但测试类里注入的是DishService,如果不是笔误的话,连目标注入类都不对。
解决方案
方案1:纯单元测试(推荐,执行速度快)
不需要引入Spring相关的依赖注入逻辑,直接补全Mockito需要的依赖即可:
- 在测试类中添加Clock的Mock/固定实例:
// 如果不需要固定时间,直接Mock即可 @Mock private Clock clock; // 如果需要固定时间做断言,直接实例化固定Clock private final Clock fixedClock = Clock.fixed(Instant.parse("2024-01-01T00:00:00Z"), ZoneOffset.UTC);
- 确保你测试类中声明的Mock覆盖了目标Service的所有依赖,Mockito会自动将这些对象注入到
@InjectMocks标注的Service实例中。
方案2:Spring集成测试(需要启动Spring上下文)
如果你确实需要用到Spring上下文的能力,调整注解配置即可:
- 把测试类的扩展替换为Spring的测试扩展,或者直接使用
@SpringBootTest组合注解:
// 方式1:基础Spring测试扩展 @ExtendWith(SpringExtension.class) // 方式2:SpringBoot集成测试注解,自带Spring扩展 @SpringBootTest(classes = RestaurantApplication.class)
- 把原来的
@Mock替换为@MockBean,让Spring把模拟的Repository实例注入到上下文里,同时上下文会自动加载启动类中声明的Clock Bean,你可以直接@Autowired注入目标Service使用,不需要再写@InjectMocks。
内容的提问来源于stack exchange,提问作者user16722881
相关产品推荐
相关产品推荐

