Mockito多次mock同一方法时when().thenReturn()返回错误值如何解决
Mockito多次Stub同一方法返回值不符合预期的解决方案
问题根因
Mockito对同一方法的Stub规则会按逆序匹配:即优先匹配最后声明的规则,匹配不到才会向前查找更早的规则。该问题通常由两个原因导致:
- Stub时使用的参数(
Object1/Object2)和实际调用时传入的参数equals判断不相等,导致前面的规则匹配失败,最终命中最后一次配置的规则 - 规则顺序配置错误,更宽泛的匹配规则放在了更具体的规则之后,覆盖了前面的窄范围规则
调整方案
方案1:使用明确的等值匹配器
直接按需求用具体参数值+eq()匹配器声明规则,确保匹配逻辑符合预期:
when(serviceA.findById(any(String.class))).thenReturn(Object1); // 明确匹配入参为1的请求 when(serviceB.getById(eq(1))).thenReturn(FirstValue); when(serviceC.convert(any(Integer.class), any(Integer.class))).thenReturn(Object2); // 明确匹配入参为2的请求 when(serviceB.getById(eq(2))).thenReturn(LatestValue); when(serviceA.save(Object2)).then(returnsFirstArg());
方案2:调整规则顺序
如果需要保留对象参数匹配的写法,先确认Object1和Object2的equals、hashCode方法逻辑正确,再把更具体的规则放在更靠后的位置:
// 先声明相对宽泛的规则 when(serviceA.findById(any(String.class))).thenReturn(Object1); when(serviceC.convert(any(Integer.class), any(Integer.class))).thenReturn(Object2); when(serviceA.save(Object2)).then(returnsFirstArg()); // 后声明更具体的serviceB规则,避免被覆盖 when(serviceB.getById(Object1)).thenReturn(FirstValue); when(serviceB.getById(Object2)).thenReturn(LatestValue);
方案3:使用doReturn写法规避Spy对象的副作用
如果serviceB是Spy对象而非纯Mock对象,when().thenReturn()的写法会触发一次真实方法调用,可能导致匹配逻辑异常,换用doReturn写法即可:
doReturn(FirstValue).when(serviceB).getById(eq(1)); doReturn(LatestValue).when(serviceB).getById(eq(2));
同参数多返回值场景补充
如果是同一个入参、多次调用需要返回不同值,可以直接链式配置返回值:
// 第一次调用返回FirstValue,第二次及之后调用返回LatestValue when(serviceB.getById(anyInt())).thenReturn(FirstValue, LatestValue);
内容的提问来源于stack exchange,提问作者jimmy
相关产品推荐
相关产品推荐

