Mockito为何无法匹配字段值相同的对象,导致方法调用始终返回null?
Mockito为何无法匹配字段值相同的对象,导致方法调用始终返回null?
嘿,这个问题我之前踩过坑!咱们来拆解一下问题出在哪,以及怎么解决~
首先得搞懂Mockito默认的参数匹配逻辑:它是用对象的equals()方法来判断传入的参数和你mock时用的参数是否匹配的。如果你的那个对象类没有重写equals(),那它就会用Object类的默认实现——也就是只判断两个对象是不是同一个内存引用,哪怕两个对象的name字段都是"Object 1",只要不是同一个对象实例,Mockito就会认为参数不匹配,自然就返回默认的null了。
知道了原因,解决方案就有这么几种:
1. 给对象类重写equals()和hashCode()
如果这个类是你自己能修改的,这是最稳妥的办法。让equals()方法比较你关心的字段(比如这里的name),这样只要字段值一致,Mockito就会认为参数匹配。举个例子:
public class YourObject { private String name; // 省略getter、setter和构造方法 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; YourObject that = (YourObject) o; return Objects.equals(name, that.name); } @Override public int hashCode() { return Objects.hash(name); } }
重写完之后,你原来的mock代码就能正常工作了。
2. 使用Mockito的参数匹配器(适合无法修改类的情况)
如果这个对象类是第三方库的,没法修改,那可以用Mockito提供的参数匹配器来基于字段值做匹配:
方法A:用refEq()匹配字段值
refEq()会忽略对象的引用,直接比较字段值,还可以指定要忽略的字段(如果有的话):
import static org.mockito.ArgumentMatchers.refEq; // 匹配所有字段值和object一致的实例 when(some_method(refEq(object))).thenReturn(someValue); // 如果有不需要比较的字段,比如id,可以这样写 when(some_method(refEq(object, "id"))).thenReturn(someValue);
方法B:用argThat()自定义匹配逻辑
如果需要更灵活的匹配规则,比如只判断name等于"Object 1",可以用argThat()写lambda表达式:
import static org.mockito.ArgumentMatchers.argThat; when(some_method(argThat(obj -> "Object 1".equals(obj.getName())))).thenReturn(someValue);
3. 自定义不匹配时的行为(可选)
如果你想让不匹配的情况抛出错误而不是返回null,可以先设置默认行为,再指定匹配的情况:
import static org.mockito.ArgumentMatchers.any; // 先设置所有不匹配的调用都抛出异常 when(some_method(any())).thenThrow(new IllegalArgumentException("传入的对象不匹配要求")); // 再设置匹配时的返回值 when(some_method(refEq(object))).thenReturn(someValue);
这样就能精准控制不同情况的行为啦!
备注:内容来源于stack exchange,提问作者Nisanio
相关产品推荐
相关产品推荐

