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
相关产品推荐
相关产品推荐

