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
相关产品推荐
相关产品推荐

