Mockito中verify对Mock生效但对Spy不生效的问题排查
关于Mockito Spy无法捕获Mock对象方法调用的问题分析
问题重现
验证失败的代码
var list = (ArrayList<String>) Mockito.mock(ArrayList.class); var spyList = Mockito.spy(list); list.add("test"); Mockito.verify(spyList).add("test"); // 此处验证失败
验证成功的代码
var list = (ArrayList<String>) Mockito.mock(ArrayList.class); //var spyList = Mockito.spy(list); list.add("test"); Mockito.verify(list).add("test"); // 此处验证成功
原因分析
- Spy与原Mock是完全独立的代理对象:Mockito的Spy本质是对目标对象的包装代理,但它和原对象(这里是Mock出来的list)是两个分离的实例。你调用
list.add("test")是直接操作原Mock,Spy没有介入这个调用流程,自然不会记录该调用行为,verify时就会失败。 - Spy的核心逻辑是拦截自身方法调用:不管目标是真实对象还是Mock对象,只有当你调用Spy实例的方法时,Spy才会拦截并记录调用。你现在绕开了Spy直接操作原对象,相当于Spy全程“没看见”这个调用。
正确写法示例
场景1:Spy真实对象(你原本的需求)
// 直接Spy真实的ArrayList实例 var realList = new ArrayList<String>(); var spyList = Mockito.spy(realList); // 必须调用Spy对象的方法,而非原真实对象的方法 spyList.add("test"); Mockito.verify(spyList).add("test"); // 验证通过
场景2:Spy Mock对象(仅作演示,实际无业务意义)
如果一定要Spy一个Mock对象并让验证通过,需要调用Spy的方法:
var list = Mockito.mock(ArrayList.class); var spyList = Mockito.spy(list); // 调用Spy的add方法,而非原Mock的方法 spyList.add("test"); Mockito.verify(spyList).add("test"); // 验证通过
补充说明
直接verify原Mock能成功,是因为原Mock本身会记录自己的方法调用行为,你调用的是它的方法,自然能被verify捕获。而Spy和它没有任何调用关联,所以无法感知到原Mock的操作。
内容的提问来源于stack exchange,提问作者Toralf Schneider
相关产品推荐
相关产品推荐

