如何对DynamoDB query操作的分页功能进行Mock与单元测试
问题原因
你当前测试代码的问题在于DynamoDB query的stub是固定返回全量数据,不会响应你接口传入的排序、分页参数(对应DynamoDB原生参数ScanIndexForward、Limit、ExclusiveStartKey),因此无法验证分页排序逻辑是否正确。
解决方案1:使用条件化Stub模拟DynamoDB行为
你可以将固定返回的stub修改为根据调用参数动态返回对应分页排序后的数据,示例修改如下:
test('should paginate backward and forward', async () => { const allTestItems = [ { convertedUrl: 'https://xxxx.awssensei.tk/ddddd', createdAt: '2021-11-04T05:50:14.180Z', originalUrl: 'https://aws.com', updatedAt: '2021-11-04T05:58:12.659Z', }, { convertedUrl: 'https://xxxx.awssensei.tk/bbbbb', createdAt: '2021-11-04T05:50:43.818Z', originalUrl: 'https://fb.com', updatedAt: '2021-11-04T05:57:42.704Z', }, { convertedUrl: 'https://xxx.awssensei.tk/eeeee', createdAt: '2021-11-04T05:50:55.121Z', originalUrl: 'https://google.com', updatedAt: '2021-11-04T05:58:21.141Z', }, { convertedUrl: 'https://xxxx.awssensei.tk/aaaaa', createdAt: '2021-11-04T05:51:06.603Z', originalUrl: 'https://instagram.com', updatedAt: '2021-11-04T05:57:14.750Z', }, ]; sandbox .stub(AWS.DynamoDB.DocumentClient.prototype, 'query') .callsFake(async (params) => { // 处理排序逻辑 let processedItems = [...allTestItems]; if (params.ScanIndexForward === false) { processedItems = processedItems.reverse(); } // 处理分页逻辑 const pageLimit = params.Limit || processedItems.length; let startIndex = 0; if (params.ExclusiveStartKey) { // 此处根据你的表排序键调整匹配逻辑,示例用createdAt作为排序键 startIndex = processedItems.findIndex(item => item.createdAt === params.ExclusiveStartKey.createdAt) + 1; } const resultItems = processedItems.slice(startIndex, startIndex + pageLimit); // 生成下一页游标 const lastEvaluatedKey = startIndex + pageLimit < processedItems.length ? { createdAt: resultItems[resultItems.length - 1].createdAt } : undefined; return { Items: resultItems, LastEvaluatedKey: lastEvaluatedKey }; }); const app = require('../app'); // 测试正序全量返回 const response = await request(app) .get('/users/auth-user/urls?sort_by=createdAt') .set('Authorization', `Bearer ${token}`); expect(response.body.history.length).toBe(4); // 追加分页测试逻辑:每页2条,测试第一页返回 const page1Res = await request(app) .get('/users/auth-user/urls?sort_by=createdAt&page_size=2') .set('Authorization', `Bearer ${token}`); expect(page1Res.body.history.length).toBe(2); expect(page1Res.body.next_cursor).toBeDefined(); // 测试第二页返回 const page2Res = await request(app) .get(`/users/auth-user/urls?sort_by=createdAt&page_size=2&cursor=${page1Res.body.next_cursor}`) .set('Authorization', `Bearer ${token}`); expect(page2Res.body.history.length).toBe(2); expect(page2Res.body.next_cursor).toBeUndefined(); });
解决方案2:使用本地DynamoDB做集成测试
如果需要更贴近生产环境的测试效果,可以直接使用本地DynamoDB实例:
- 本地启动DynamoDB Docker容器,将SDK请求端点指向本地实例
- 测试前置逻辑中创建对应表、批量写入预设测试数据
- 测试完成后清空表数据即可,不需要修改业务代码的query逻辑
内容的提问来源于stack exchange,提问作者Jatin Mehrotra
相关产品推荐
相关产品推荐

