如何使用Jest对注入DynamoDB.DocumentClient的服务做单元测试?
解决DynamoDB.DocumentClient Jest Mock的TypeScript类型错误
问题根源
你遇到的TS2339错误,是因为TypeScript无法识别promise()方法是Jest Mock函数——默认情况下,TypeScript会用AWS SDK的原始类型定义它,而原始类型里没有mockResolvedValueOnce这类Mock方法。
解决方案
直接创建类型明确的Mock实例,显式把query和promise标记为jest.Mock,同时因为你用的是依赖注入,不需要额外Mockaws-sdk模块(模块Mock适合直接导入使用的场景,依赖注入是传入实例,直接Mock实例更简单)。
完整修复后的测试代码
import { CatsService } from './cats.service'; import { Repository } from 'typeorm'; import { DynamoDB } from 'aws-sdk'; import { CatEntity } from 'somewhere'; // Mock TypeORM仓库(保持原有逻辑) const mockCatRepository = { findOne: jest.fn(), } as unknown as Repository<CatEntity>; describe('CatsService', () => { let service: CatsService; // 显式定义mockClientDB的类型,让query和promise都是jest.Mock let mockClientDB: { query: jest.Mock; } as unknown as DynamoDB.DocumentClient; // 单独保存promise的Mock引用,方便后续调用Mock方法 let mockDynamoPromise: jest.Mock; beforeEach(() => { mockDynamoPromise = jest.fn(); // 创建query的Mock函数,返回包含promise Mock的对象 mockClientDB = { query: jest.fn().mockReturnValue({ promise: mockDynamoPromise }), } as unknown as DynamoDB.DocumentClient; service = new CatsService(mockCatRepository, mockClientDB); }); it('should return a cat successfully', async () => { const mockInput = 'Peanut'; const mockDynamoReturn = { Items: [{ name: 'Peanut', breed: 'Tabby' }] }; // 直接用保存的promise Mock设置返回值 mockDynamoPromise.mockResolvedValueOnce(mockDynamoReturn); const result = await service.findCat(mockInput); expect(mockClientDB.query).toHaveBeenCalledWith(mockInput); expect(result).toEqual(mockDynamoReturn); }); });
关键调整点
- 移除不必要的模块Mock:
jest.mock('aws-sdk')对你的依赖注入场景没用,反而会干扰类型推断,直接删除。 - 单独保存promise Mock引用:避免从query的返回值中嵌套获取promise,让测试代码更直观,同时明确告诉TypeScript这是Jest Mock函数。
- 类型断言精准控制:通过
as unknown as DynamoDB.DocumentClient将自定义的Mock对象适配为AWS SDK的类型,既满足类型检查,又保留Mock方法的可调用性。
额外提示
- 如果需要Mock多个DynamoDB方法(比如
get、put),可以扩展mockClientDB的结构,每个方法都返回带对应promise Mock的对象。 - 确保
CatDTO类型与DynamoDB返回的结构匹配,避免后续出现类型不兼容的错误。
内容的提问来源于stack exchange,提问作者José Gabriel Alves
相关产品推荐
相关产品推荐

