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

如何Mock父类的final方法isRunning()解决单元测试空指针问题?

问题根因

你遇到的空指针问题是因为isRunning()是父类AbstractScheduledService的final方法,Mockito默认不支持mock final方法,调用mock对象的final方法时会直接执行父类的原有实现,而父类isRunning()的实现依赖内部的状态成员变量,mock出来的MyService实例没有初始化这些内部变量,因此触发空指针异常。

最优解决方案

根据你的场景可以选择以下两种方案:

方案1:启用Mockito final方法mock能力(侵入性最低,改动最小)

该方案适用于Mockito 2.1.0及以上版本,无需修改业务代码,只需调整单元测试配置即可:

  1. 在测试资源目录src/test/resources下新建mockito-extensions目录,在该目录下创建名为org.mockito.plugins.MockMaker的文件
  2. 文件内写入以下内容:
mock-maker-inline
  1. 配置完成后就可以正常对isRunning()方法打桩:
// 模拟服务正常运行的场景
when(myService.isRunning()).thenReturn(true);
// 模拟服务异常的场景
when(myService.isRunning()).thenReturn(false);

如果使用JUnit 5 + Mockito 3.5以上版本,还可以通过注解直接为单测类开启该能力,无需新增配置文件:

@ExtendWith(MockitoExtension.class)
@MockitoSettings(mockMaker = MockMaker.INLINE)
public class MyServiceHealthcheckTest {
    @Mock 
    MyService myService;
    // 后续测试逻辑
}

方案2:依赖倒置解耦(设计层面优化,符合最佳实践)

如果不想修改Mockito的全局配置,可以从代码设计层面解耦,避免单元测试受父类final方法限制:

  1. 定义健康检查通用接口:
public interface HealthCheckable {
    boolean isRunning();
}
  1. 修改MyService实现该接口:
public class MyService extends AbstractScheduledService implements HealthCheckable {}
  1. 健康检查类改为依赖接口而非具体的MyService实现:
public class MyServiceHealthcheck {
    HealthCheckable myService;
       
    @Inject
    public MyServiceHealthCheck(HealthCheckable myService) {
        this.myService = myService;
    }

    public boolean isHealthy() {
        return myService.isRunning();
    }
}
  1. 单元测试时直接mockHealthCheckable接口即可,完全不需要处理final方法的限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 19:54:03