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

切换至mockito-inline导致logback-classic抛出空指针异常求助

问题原因及修复方案

核心原因

Mockito-inline 4.11.0通过字节码生成创建的Mock异常实例,没有初始化Throwable类中的suppressed数组(JVM默认会将该数组初始化为空数组,但Mockito-inline的mock逻辑跳过了这一步)。而Logback 1.2.11的ThrowableProxy构造方法中直接访问这个数组的length属性,未做null校验,因此抛出NPE。

可行修复方案

  • 升级Logback版本(最优解):Logback在1.2.12版本中修复了这个NPE问题,直接将logback-classic和logback-core升级至1.2.12或更高版本,无需修改业务代码,既能保留堆栈信息,又能正常使用Mockito-inline的特性。
  • 包装Mock异常(临时兼容方案):如果暂时无法升级Logback,在日志打印前把mock的异常包装成普通RuntimeException,确保suppressed数组正常初始化,示例代码:
catch (Throwable oe) {
    // 用普通异常包装mock异常,保留原信息和堆栈
    Throwable safeThrowable = new RuntimeException(oe.getMessage(), oe);
    LOG.warn(
        "{} while registering RIC {}, will retry once: {}",
        oe.getClass().getSimpleName(), ric, safeThrowable.getMessage(), safeThrowable);
}
  • 切换Mockito Mock实现(妥协方案):如果不需要Mockito-inline的特性(比如mock final类、静态方法),可以改回传统的CGLIB代理。在测试类上添加注解:
@MockSettings(mockMaker = MockMakerType.CGLIB)

或者在src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker文件中写入:

mock-maker-class=org.mockito.internal.creation.cglib.CglibMockMaker

此方案会放弃inline mock的能力,但能避免NPE问题。

为什么之前的参数调整无效

不管是直接传oe还是重复传oe,只要Logback需要处理这个mock的Throwable实例,就会触发ThrowableProxy的构造逻辑,而mock异常的suppressed数组为null,必然抛出NPE;仅传oe.toString()是因为没有让Logback处理Throwable实例,所以不会触发异常,但丢失了堆栈信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 02:06:24