Spring Mockito:含列表对象作为参数时匹配无序列表的方法
解决Mockito中PageRequest按无序ids列表匹配的问题
当前测试里用eq(pageRequest)匹配时,只要PageRequest的ids列表顺序和预设的不一样,就会匹配失败返回null——根本原因是默认的eq会严格对比对象的所有属性(包括列表顺序)。要解决这个问题,你可以用以下几种方式配置忽略顺序的匹配规则:
方法一:自定义ArgumentMatcher
自己写一个匹配器类,专门用来判断两个PageRequest的ids是否包含相同元素(不管顺序),还能顺便处理其他需要匹配的字段:
import org.mockito.ArgumentMatcher; import java.util.Set; import java.util.stream.Collectors; public class PageRequestIdsMatcher implements ArgumentMatcher<PageRequest> { private final PageRequest expected; public PageRequestIdsMatcher(PageRequest expected) { this.expected = expected; } @Override public boolean matches(PageRequest actual) { if (expected == null || actual == null) { return expected == actual; } // 转成集合对比,忽略顺序 Set<String> expectedIds = expected.getIds().stream().collect(Collectors.toSet()); Set<String> actualIds = actual.getIds().stream().collect(Collectors.toSet()); // 如果还有分页、排序这类其他字段要匹配,直接加判断就行 return expectedIds.equals(actualIds) && expected.getPage() == actual.getPage() && expected.getSize() == actual.getSize(); } }
测试代码里这么用:
PageRequest pageRequest = PageRequest.builder() .ids(List.of(serviceId2, serviceId1, serviceId3)) .build(); when(client.getServices(argThat(new PageRequestIdsMatcher(pageRequest)))).thenAnswer(a -> { // 你的业务逻辑实现 });
方法二:用Hamcrest的无序匹配器快速实现
如果项目里已经引入了Hamcrest依赖,可以直接用它的containsInAnyOrder来简化代码,不用写单独的匹配器类:
import static org.hamcrest.Matchers.containsInAnyOrder; import static org.mockito.ArgumentMatchers.argThat; // ... PageRequest pageRequest = PageRequest.builder() .ids(List.of(serviceId2, serviceId1, serviceId3)) .build(); when(client.getServices(argThat(pr -> // 匹配ids是否包含相同元素,顺序无关 containsInAnyOrder(pageRequest.getIds().toArray()).matches(pr.getIds()) // 同样,需要的话加其他字段匹配 && pr.getPage() == pageRequest.getPage() ))).thenAnswer(a -> { // 你的业务逻辑实现 });
方法三:修改PageRequest的equals方法(谨慎使用)
如果PageRequest是你自己维护的类,可以重写它的equals和hashCode方法,让ids的对比忽略顺序。但这种方式会影响所有用到这个类的地方,要是其他业务场景需要严格对比顺序,就会出问题,所以除非确定全局都需要无序匹配,否则不推荐:
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PageRequest that = (PageRequest) o; // 转成HashSet对比ids,忽略顺序 Set<String> thisIds = new HashSet<>(this.ids); Set<String> thatIds = new HashSet<>(that.ids); return Objects.equals(thisIds, thatIds) && Objects.equals(this.getPage(), that.getPage()) && Objects.equals(this.getSize(), that.getSize()); } @Override public int hashCode() { // hashCode要和equals对应,用HashSet的hash值 return Objects.hash(new HashSet<>(ids), getPage(), getSize()); }
内容的提问来源于stack exchange,提问作者Khanna111
相关产品推荐
相关产品推荐

