Mockito 1.9.5中eq()匹配器调用Mock方法验证失败问题排查
问题原因分析
这事儿核心在于Mockito参数匹配器的执行时机:
- 当你写
eq(user.getName())时,这个表达式是在执行verify()方法的验证阶段才会计算user.getName()的值,而不是在someDaoMethod被实际调用的阶段。 - 如果在
someDaoMethod调用完成后,user对象的name属性被修改了(比如业务逻辑里更新了user的名字,或者测试代码里不小心改动了它),那验证时拿到的user.getName()就是修改后的值,和实际调用方法时传入的原始值不匹配,自然就验证失败了。 - 而用局部变量
name = user.getName()时,这个变量在方法调用前就保存了原始的name值,验证时用的是这个固定值,所以能匹配成功。
另外还有一种少见的情况:如果user是Mockito的spy对象,且你在调用someDaoMethod后对user.getName()做了stub修改,也会导致验证时的返回值和调用时不一致。
不用局部变量的解决方法
推荐用ArgumentCaptor来捕获实际调用时的参数,完全不需要额外的局部变量:
// 1. 定义参数捕获器 ArgumentCaptor<String> nameCaptor = ArgumentCaptor.forClass(String.class); // 2. 验证方法调用,并用捕获器捕获第二个参数 verify(someDao).someDaoMethod(any(), nameCaptor.capture()); // 3. 断言捕获到的参数和预期值一致 assertEquals(user.getName(), nameCaptor.getValue());
这种方式的好处是直接捕获方法调用时传入的真实参数,不受后续user对象变化的影响,逻辑更清晰。
另外还有一种思路:如果能确保在验证阶段user.getName()的返回值和调用时完全一致(比如测试代码里不会修改user,或者user是不可变对象),那其实eq(user.getName())本身是可以正常工作的,但这种方式依赖外部条件,不如ArgumentCaptor可靠。
内容的提问来源于stack exchange,提问作者Vitalii Vitrenko
相关产品推荐
相关产品推荐

