You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 17:20:48