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

Mockito 3.6.28调用doCallRealMethod抛出NullPointerException问题求助

问题根因
  • Mockito 的 @InjectMocks 注解只会为被它直接修饰的对象注入测试类中声明的@Mock依赖:你代码里仅ClassA实例会被自动注入LoggingService和ClassB的Mock实例。
  • 你声明的@Mock ClassB classB本身是Mockito生成的代理对象,@InjectMocks不会为这个Mock代理对象自动注入它自身需要的LoggingService依赖。当你通过doCallRealMethod()调用ClassB的真实业务方法时,ClassB实例内部的loggingService仍为null,因此抛出空指针异常。
可行解决方案

方案1:手动为Mock的ClassB注入依赖

可以借助Spring Test提供的ReflectionTestUtils快速赋值,也可以用Java原生反射实现,示例如下:

@RunWith(MockitoJUnitRunner.Silent.class)
public class TestClass{

    @InjectMocks
    ClassA classA;
    
    @Mock
    ClassB classB;
    
    @Mock
    private LoggingService loggingService;
    
    @Before
    public void initDependency() {
        // 手动给ClassB的mock实例注入loggingService
        ReflectionTestUtils.setField(classB, "loggingService", loggingService);
    }
    
    @Test
    public void testMethod(){
        doCallRealMethod().when(classB).doSomething(); 
        classA.doSomething();
    }
}

方案2:用Spy替代Mock来持有真实ClassB实例

如果不需要MockClassB的其他方法,直接用@Spy修饰真实的ClassB实例,配合@InjectMocks(Mockito 3.3+版本支持)自动为其注入依赖:

@RunWith(MockitoJUnitRunner.Silent.class)
public class TestClass{

    @InjectMocks
    ClassA classA;
    
    @Spy
    @InjectMocks
    ClassB classB = new ClassB();
    
    @Mock
    private LoggingService loggingService;
    
    @Test
    public void testMethod(){
        // Spy默认调用真实方法,无需额外配置doCallRealMethod
        classA.doSomething();
    }
}

方案3:重构业务代码使用构造注入(推荐)

放弃字段注入改用构造注入,从根源上避免测试时依赖注入失效的问题,同时代码可维护性更高:

// 重构后的ClassB
public class ClassB{
    private final LoggingService loggingService;
    
    @Autowired
    public ClassB(LoggingService loggingService) {
        this.loggingService = loggingService;
    }
    
    public void doSomething(){        
        loggingService.info("info log");
    }
}

// 重构后的ClassA
public class ClassA{
    private final LoggingService loggingService;
    private final ClassB classB;
    
    @Autowired
    public ClassA(LoggingService loggingService, ClassB classB) {
        this.loggingService = loggingService;
        this.classB = classB;
    }

    public void doSomething(){
        loggingService.info("info log");
        classB.doSomething();
    }
}

重构后原有测试代码无需调整,Mockito会自动识别构造方法参数,为所有实例注入对应的Mock依赖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 00:09:03