如何切换Jest模拟:从返回值切换为抛出错误(AWS DynamoDB测试场景)
解决Jest模拟DynamoDB返回值与抛出错误切换的问题
核心问题分析
你的测试失败是因为DynamoDBClient的send方法被固定为返回'get success',无法在不同测试用例中切换行为;同时出现的类型错误是因为TypeScript无法识别模拟后的类/方法是Jest Mock对象,需要显式断言类型。
修正后的测试代码
db.unit.ts:
import { getData } from './db'; import { GetItemCommand, DynamoDBClient } from '@aws-sdk/client-dynamodb'; // 模拟AWS SDK模块 jest.mock('@aws-sdk/client-dynamodb', () => ({ GetItemCommand: jest.fn(), DynamoDBClient: jest.fn(() => ({ // 先定义空的mock函数,后续在测试用例中修改行为 send: jest.fn() })) })); // 获取模拟的send方法,并断言为Jest Mock类型 const mockSend = (DynamoDBClient as jest.Mock).mockReturnValue({ send: jest.fn() }).send as jest.Mock; beforeEach(() => { // 重置所有mock状态,避免测试用例互相干扰 jest.clearAllMocks(); }); it('正常流程:成功获取数据', async () => { // 让send方法返回成功结果 mockSend.mockResolvedValueOnce('get success'); const res = await getData(); expect(res).toBe('get success'); expect(GetItemCommand).toHaveBeenCalled(); expect(mockSend).toHaveBeenCalledWith(expect.any(GetItemCommand)); }); it('异常流程:获取数据时抛出错误', async () => { // 让send方法抛出错误 mockSend.mockRejectedValueOnce(new Error('DynamoDB调用失败')); // 测试getData是否抛出预期的错误 await expect(getData()).rejects.toThrow('some error here'); expect(mockSend).toHaveBeenCalled(); });
关键修改点说明
- 动态控制send方法行为:不再在
jest.mock中固定send的返回值,而是将其定义为空的mock函数,在每个测试用例中通过mockResolvedValueOnce(成功)或mockRejectedValueOnce(失败)设置对应行为。 - 类型断言解决报错:将
DynamoDBClient和send方法显式断言为jest.Mock类型,解决TypeScript的Property mockReturnValueOnce does not exist错误。 - 重置mock状态:使用
beforeEach和jest.clearAllMocks()确保每个测试用例的mock状态独立,避免互相干扰。 - 正确的错误测试方式:测试异步函数抛出错误时,需要用
await expect(fn()).rejects.toThrow(...),而不是先调用函数再断言返回值抛出错误。
关于你之前的错误尝试
你之前调用UpdateItemCommand.mockReturnValueOnce(true)时出现类型错误,是因为TypeScript默认认为UpdateItemCommand是原SDK的类类型,而非Jest Mock对象。需要将其断言为jest.Mock才能调用mock相关方法:
// 正确写法 (UpdateItemCommand as jest.Mock).mockReturnValueOnce(true);
内容的提问来源于stack exchange,提问作者physicsboy
相关产品推荐
相关产品推荐

