Mockito Spy监视ArrayList调用add方法触发空指针异常问题咨询
Mockito Spy ArrayList调用add时触发NullPointerException的根本原因
问题场景
编写单元测试时,需要用Mockito.Spy监视ArrayList来校验方法调用情况,但调用add方法准备测试数据时触发了NullPointerException。
普通ArrayList添加元素完全正常:
ArrayList<Integer> idlist1 = new ArrayList<Integer>(); idlist1.add(39);
但使用Spy的场景中,即便Spy默认会调用对象的真实方法,add调用依然失败:
ArrayList<Integer> idlist2 = Mockito.spy(new ArrayList<Integer>()); idlist2.add(39);
错误信息
NullPointerException: Cannot read the array length because "elementData" is null
调试发现,执行到ArrayList::add时,因elementData为null,导致add(e, elementData, 0)调用失败。明明ArrayList构造方法会把elementData初始化为空数组,但Spy似乎把它重置成了null。
临时解决方案
- 不使用Spy监视List
- 先向真实List添加元素,再基于这个已初始化的List创建Spy
根本原因
核心问题出在ArrayList的elementData字段和Mockito的Spy实现机制上:
- ArrayList的
elementData是用transient修饰的,这个关键字表示该字段不需要被序列化。 - Mockito生成Spy代理时,默认会忽略transient字段的初始化值复制。虽然你通过
new ArrayList<>()执行了构造方法,原对象的elementData已经被初始化为空数组,但Mockito创建的代理实例并没有继承这个字段值,导致代理对象的elementData为null。 - 当调用代理对象的
add方法时,真实的ArrayList.add逻辑被执行,但此时elementData是null,访问它的长度自然就抛出了NullPointerException。
内容的提问来源于stack exchange,提问作者Poppet
相关产品推荐
相关产品推荐

