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

