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

Spring Mockito:Repository Mock指定参数调用返回Null问题

问题分析

你遇到的NullPointerException本质是测试中手动创建的PageRequest实例和控制器实际传入的PageRequest实例不相等,导致Mock的匹配条件不触发,Repository方法返回null,后续处理分页数据时抛出NPE。

控制器里是基于传入的Pageable构建带排序的PageRequest,而你测试里写的PageRequest.of(0,2)大概率缺少排序参数,或者排序规则和控制器里的不一致——PageRequest的equals方法会严格比较页码、每页大小、排序规则等所有属性,只要有一个属性不匹配,两个实例就判定为不等,Mock逻辑也就不会命中。

解决方法

1. 精准复刻控制器的PageRequest实例

先明确控制器里构建PageRequest的完整逻辑,比如控制器代码可能是这样的:

// 控制器中构建带排序的PageRequest
Pageable pageable = PageRequest.of(page, size, Sort.by("createTime").descending());
notioRepository.findByOwner("tom", pageable);

那测试里就要完全复刻这个PageRequest的所有属性:

// 完全匹配控制器的分页+排序规则
PageRequest expectedPage = PageRequest.of(0, 2, Sort.by("createTime").descending());
when(notioRepository.findByOwner("tom", expectedPage))
    .thenReturn(new PageImpl<>(Arrays.asList(todo1, todo2), expectedPage, 10));

2. 用自定义参数匹配器校验核心属性

如果不想完全复刻实例,可以用ArgumentMatchers的自定义匹配逻辑,只校验你关心的核心属性:

when(notioRepository.findByOwner(eq("tom"), argumentMatchers(pageable -> 
    pageable.getPageNumber() == 0 && 
    pageable.getPageSize() == 2 &&
    pageable.getSort().getOrderFor("createTime") != null // 可选,校验排序字段存在
))).thenReturn(new PageImpl<>(todoList, PageRequest.of(0,2), todoList.size()));

这种方式不需要完全匹配PageRequest实例,只要核心属性符合预期就能触发Mock。

3. 对齐MockMvc请求的分页参数

如果测试是通过MockMvc发起请求,要确保请求参数里的分页、排序和Mock的规则一致,比如:

mockMvc.perform(get("/todos")
        .param("owner", "tom")
        .param("page", "0")
        .param("size", "2")
        .param("sort", "createTime,desc")) // 和Mock的排序规则对齐
    .andExpect(status().isOk());
关键注意点
  • PageRequest的equals方法会严格校验所有属性,哪怕排序字段大小写不一致、排序方向不同,都会导致匹配失败。
  • 不要用无排序的PageRequest.of(0,2)去匹配控制器里带排序的PageRequest,必须保证两者的排序规则完全一致。

内容的提问来源于stack exchange,提问作者Melvin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 04:22:17