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

Mockito测试集成Mybatis PageHelper的DAO方法时PageInfo.getList()返回空列表

问题:Mockito测试集成PageHelper的代码时,PageInfo.getList()返回空列表

待测试类代码:

import com.github.pagehelper.ISelect;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
class AService{
private SomeDao aDao;
   public void aMethod(){
            // 省略其他逻辑
            ISelect iSelect = () -> aDao.queryById(queryStatement);
            PageInfo<Stuff> pageInfo = PageHelper.startPage(pageNum, pageSize).doSelectPageInfo(iSelect);
            List<Stuff> stuffs = pageInfo.getList();
   }
}

测试类代码:

import ...
class serviceTest{
   @Mock
   public SomeDao aDao;
   @InjectMocks 
   public AService service;
   // 省略其他初始化代码
   @Test
   public void testMethod(){
     List<Stuff> list = Collections.singletonList(new Stuff());
     Mockito.when(aDao.queryById(any(QueryStatement.class))).thenAnswer((inv)->{
            System.out.println("stub of aDao.queryById is called");
            return list;
        });
     // 调用service.aMethod()并验证结果
   }
}

执行测试后,已通过日志确认DAO的Stub方法被调用,但pageInfo.getList()返回空列表,期望返回模拟的Stuff列表。


原因及解决方案

原因

PageHelper依赖MyBatis的拦截器机制实现分页:在真实环境中,它会拦截MyBatis的SQL查询请求,执行分页逻辑后将结果封装到PageInfo中。但单元测试中我们Mock了DAO层,跳过了MyBatis的完整执行流程,PageHelper无法拦截到有效查询结果,因此不会将DAO返回的列表填充到PageInfo里,最终导致getList()为空。

解决方案

1. 静态Mock PageHelper,直接返回构造好的PageInfo

利用Mockito的静态Mock能力,模拟PageHelper.startPage()和后续的doSelectPageInfo()行为,直接返回我们预设的PageInfo对象:

@Test
public void testMethod(){
    List<Stuff> mockList = Collections.singletonList(new Stuff());
    PageInfo<Stuff> expectedPageInfo = new PageInfo<>(mockList);

    // 静态Mock PageHelper类
    try (MockedStatic<PageHelper> mockedPageHelper = Mockito.mockStatic(PageHelper.class)) {
        // 模拟startPage返回的Page对象
        Page<Stuff> mockPage = Mockito.mock(Page.class);
        // 让doSelectPageInfo直接返回预设的PageInfo
        Mockito.when(mockPage.doSelectPageInfo(Mockito.any(ISelect.class))).thenReturn(expectedPageInfo);
        
        // 模拟startPage方法返回mockPage
        mockedPageHelper.when(() -> PageHelper.startPage(Mockito.anyInt(), Mockito.anyInt()))
                        .thenReturn(mockPage);

        // 执行待测试方法
        service.aMethod();

        // 这里可以添加断言,验证业务逻辑是否正确使用了分页结果
    }
}

2. 禁用PageHelper(仅测试核心业务逻辑)

如果不需要验证分页逻辑,仅测试业务流程,可以在测试启动时禁用PageHelper:

@BeforeEach
void setUp() {
    // 禁用PageHelper分页插件
    PageHelper.startPage(0, 0);
    PageHelper.clearPage();
}

这种方式下,PageInfo会直接使用DAO返回的列表,但分页参数不会生效,适合只关注业务逻辑的场景。

3. 搭建集成测试环境(完整验证分页逻辑)

若需要完整验证PageHelper的分页行为,可搭建嵌入式数据库(如H2),使用真实的MyBatis映射文件和数据源,让PageHelper在真实的MyBatis流程中工作。这属于集成测试范畴,能覆盖分页逻辑的完整场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 22:13:21