使用Jest模拟S3的listObjectsV2时提示属性不存在,求排查原因
问题:Jest模拟S3 listObjectsV2方法报错:
Property 'listObjectsV2' does not exist in the provided object 我正在编写Jest单元测试,尝试使用spyOn函数模拟S3的listObjectsV2方法,代码如下:
import { S3 } from 'aws-sdk'; jest.spyOn<any, any>(S3.prototype, 'listObjectsV2').mockReturnValue({ promise: () => Promise.resolve({ $response: { Contents: [ { Key: 'assets/file1', Size: 5 }, { Key: 'assets/file2', Size: 5 }, { Key: 'assets/excluded-file2', Size: 5 }, ], }, }), });
运行时出现错误:Property 'listObjectsV2' does not exist in the provided object,请问该问题的原因是什么?
原因及解决办法
核心原因
aws-sdk v2的S3客户端方法是动态生成的,并非直接挂载在S3.prototype上的固定属性。这些方法是在实例化S3客户端时,通过内部逻辑动态添加到实例上的,所以直接尝试spyOn(S3.prototype, 'listObjectsV2')会找不到对应属性,触发报错。
解决办法
1. 直接mock整个S3类
通过jest.mock直接模拟S3类的实现,确保实例化后的对象包含mock的listObjectsV2方法:
jest.mock('aws-sdk', () => ({ S3: jest.fn().mockImplementation(() => ({ listObjectsV2: jest.fn().mockReturnValue({ promise: () => Promise.resolve({ Contents: [ { Key: 'assets/file1', Size: 5 }, { Key: 'assets/file2', Size: 5 }, { Key: 'assets/excluded-file2', Size: 5 }, ], }) }) })) }));
2. 使用aws-sdk-mock库(推荐)
专门针对aws-sdk的mock工具,简化方法模拟流程:
import AWSMock from 'aws-sdk-mock'; import { S3 } from 'aws-sdk'; // 模拟listObjectsV2方法 AWSMock.mock('S3', 'listObjectsV2', (params, callback) => { callback(null, { Contents: [ { Key: 'assets/file1', Size: 5 }, { Key: 'assets/file2', Size: 5 }, { Key: 'assets/excluded-file2', Size: 5 }, ], }); }); // 测试完成后恢复原方法 afterEach(() => { AWSMock.restore('S3', 'listObjectsV2'); });
3. 针对单个实例spyOn
如果测试中只使用一个S3实例,可以先实例化再spyOn实例上的方法:
import { S3 } from 'aws-sdk'; const s3 = new S3(); // 对实例方法进行spy const listSpy = jest.spyOn(s3, 'listObjectsV2').mockReturnValue({ promise: () => Promise.resolve({ Contents: [ { Key: 'assets/file1', Size: 5 }, { Key: 'assets/file2', Size: 5 }, { Key: 'assets/excluded-file2', Size: 5 }, ], }) }); // 测试代码中使用该s3实例
内容的提问来源于stack exchange,提问作者omer727
相关产品推荐
相关产品推荐

