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

Mockito 4.11.0 mock继承Groovy抽象类的类时抛出NPE求助

问题原因分析

Groovy 2.x对抽象类的字节码生成有特殊处理:当子类继承抽象父类时,Groovy会在子类中注入元编程相关的内部字段与逻辑。Mockito 4.x默认使用CGLIB创建代理对象时,没有正确初始化这些Groovy特有的内部依赖,导致调用mock对象的任何方法时都会触发空指针异常。而移除父类的abstract修饰后,Groovy生成的子类字节码结构和普通Java类一致,Mockito可以正常处理代理初始化,因此不会出现NPE。

解决方案

以下是几种可行的解决方式,按推荐程度排序:

1. 使用Mockito Spy替代Mock

Spy基于真实类实例创建代理,能保留Groovy的内部结构初始化逻辑,避免NPE。注意如果不想触发真实方法的执行,要使用doReturn语法(而非when...thenReturn):

@Test
void testMe() {
    Demo demo = Mockito.spy(new Demo())
    // 避免执行真实isValid方法,直接返回指定值
    Mockito.doReturn(false).when(demo).isValid()
    Mockito.doReturn(true).when(demo).bar()
    
    // 验证结果
    assert !demo.isValid()
    assert demo.bar()
}

2. 指定Mock时使用构造函数初始化

通过withSettings().useConstructor()强制Mockito调用类的构造函数完成初始化,确保Groovy内部字段被正确初始化:

@Test
void testMe() {
    Demo demo = Mockito.mock(Demo.class, Mockito.withSettings().useConstructor())
    when(demo.isValid()).thenReturn(false)
    when(demo.bar()).thenReturn(true)
    
    assert !demo.isValid()
    assert demo.bar()
}

3. 升级Groovy版本

Groovy 3.x及以上版本优化了字节码生成逻辑,和Mockito的兼容性更好。将Groovy版本升级到3.0+后,直接使用原有的mock代码即可正常运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 10:53:22