JUnit5+Mockito+SpringBoot中如何给@Spy对象注入@Mock依赖
解决Mockito Spy对象依赖注入NullPointerException问题
你的问题核心是手动初始化Spy对象时,传入的@Mock实例还未被Mockito完成初始化,同时在同一个字段上混用@Spy和@InjectMocks会干扰Mockito的注入逻辑,导致MyTargetHelper内部的databaseService为null。
以下是两种可行的解决方案:
方案一:让Mockito自动管理Spy的创建与注入
去掉MyTargetHelper的手动实例化,让Mockito通过注解完成Spy创建和依赖注入:
@ExtendWith(MockitoExtension.class) class TargetTest { @InjectMocks Target target; @Mock DatabaseService databaseService; @Mock AlertService alertService; @Spy Map<SomeEnum, Double> someMap = new EnumMap<>(SomeEnum.class); // 移除手动new,由Mockito创建Spy并注入依赖 @Spy @InjectMocks MyTargetHelper inputHelper; static final List<InputPojo> inputs; static { // 保留inputs和someMap的初始化逻辑 someMap.put(SomeEnum.EXAMPLE, 0.5); inputs = List.of(new InputPojo("id1"), new InputPojo("id2")); } @Test @SneakyThrows void testTarget() { when(databaseService.fetchForId(anyString())).thenReturn("fetch success"); target.testMethod(inputs); // 验证Helper方法调用(可选) verify(inputHelper, times(1)).process(inputs); } }
方案二:手动创建实例后转为Spy(更可控)
如果需要更精准地控制实例创建流程,可以先初始化所有依赖,再将真实实例包装为Spy,最后手动注入到Target:
@ExtendWith(MockitoExtension.class) class TargetTest { Target target; @Mock DatabaseService databaseService; @Mock AlertService alertService; @Spy Map<SomeEnum, Double> someMap = new EnumMap<>(SomeEnum.class); MyTargetHelper inputHelper; static final List<InputPojo> inputs; static { // 初始化inputs和someMap someMap.put(SomeEnum.EXAMPLE, 0.5); inputs = List.of(new InputPojo("id1"), new InputPojo("id2")); } @BeforeEach void setUp() { // 创建真实Helper实例,传入已准备好的依赖 MyTargetHelper realHelper = new MyTargetHelper(someMap, alertService, databaseService); // 包装为Spy,保留真实逻辑同时支持验证/ stub inputHelper = Mockito.spy(realHelper); // 手动注入到Target target = new Target(inputHelper); } @Test @SneakyThrows void testTarget() { when(databaseService.fetchForId(anyString())).thenReturn("fetch success"); target.testMethod(inputs); } }
关键注意事项
- 避免在@Spy字段上手动new对象:Mockito的@Mock对象初始化晚于测试类实例化,手动传入的是未初始化的null,导致依赖注入失败。
- @Spy与@InjectMocks配合时,Mockito会自动将@Mock/@Spy依赖注入到Spy对象中,无需手动实例化。
- 使用Spy的核心是保留目标类的真实业务逻辑,上述方案均能保证Helper的真实process方法被执行,同时Mock的DatabaseService和AlertService能正常工作。
内容的提问来源于stack exchange,提问作者CodeTalker
相关产品推荐
相关产品推荐

