You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mockito spy部分mock类时@Autowired依赖为null报NPE如何解决

问题原因

通过spy(CredentialsService.class)手动创建spy对象时,Mockito会直接调用CredentialsService的无参构造方法生成全新实例,整个过程完全脱离Spring IoC容器:Spring感知不到这个对象的存在,自然不会为其完成@Autowired标记的依赖注入流程。因此类中声明的私有成员encryptionService没有被赋值,保持对象默认初始值null,调用到依赖该字段的逻辑时就会抛出空指针异常。
这个手动创建的spy对象和Spring容器中管理的CredentialsService类型Bean没有任何关联,自然不会持有容器中注入的EncryptionService真实实例。

修复方案

根据测试场景选择对应方案即可:

  • 基于Spring测试上下文的集成测试场景:直接使用@SpyBean注解替代手动创建spy对象的逻辑,不要手动调用spy()方法。示例代码:
    @SpringBootTest
    public class CredentialsServiceTest {
        // 注解生成的spy对象由Spring容器完成所有依赖注入
        @SpyBean
        private CredentialsService partialMock;
    
        @Test
        void testProcess() {
            // 仅mock需要打桩的方法,spy打桩优先用doReturn语法避免提前触发真实调用
            doReturn(模拟返回值).when(partialMock).待mock的方法名(任意参数);
            // 调用待测试方法,其余逻辑走真实实现,依赖也都是容器注入的真实实例
            partialMock.process(client, id, url, null, userDetails);
        }
    }
    
  • 不启动Spring容器的纯单元测试场景:手动创建spy对象后,通过反射工具给私有依赖字段赋值即可,不需要启动整个Spring容器,执行速度更快。示例代码:
    public class CredentialsServiceTest {
        private CredentialsService partialMock;
        // 可以根据测试需要传入EncryptionService真实实例,也可以传入mock对象
        private EncryptionService encryptionService = new EncryptionService();
    
        @BeforeEach
        void setUp() {
            partialMock = spy(CredentialsService.class);
            // 给spy对象的私有成员encryptionService注入准备好的实例
            ReflectionTestUtils.setField(partialMock, "encryptionService", encryptionService);
        }
    
        @Test
        void testProcess() {
            // 打桩需要mock的特定方法后执行测试逻辑
            doReturn(模拟返回值).when(partialMock).待mock的方法名(任意参数);
            partialMock.process(client, id, url, null, userDetails);
        }
    }
    

注意:给spy对象打桩时不要直接写when(partialMock.待mock方法()).thenReturn(xxx),这种写法会先执行一次待mock方法的真实逻辑,可能提前触发空指针或其他非预期行为,统一用doReturn(xxx).when(partialMock).待mock方法()的写法。

内容的提问来源于stack exchange,提问作者TheUnreal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 11:06:16