使用Jest模拟AWS SDK的deleteObject和upload函数时的TypeScript类型错误
解决AWS SDK S3的deleteObject和upload方法Jest模拟类型错误问题
业务代码场景
我需要为后端路由中使用的AWS SDK S3 deleteObject和upload方法编写Jest模拟,业务代码如下:
删除对象代码
const params: AWS.S3.DeleteObjectRequest = { Bucket: bucketName, Key: fileName, }; // 从存储桶中删除对象 await s3.deleteObject(params).promise();
上传对象代码
const params: AWS.S3.PutObjectRequest = { Bucket: bucketName, Key: filename, Body: file.data, }; // 将文件上传到S3 const data = await s3.upload(params).promise();
尝试的模拟方式及报错
我尝试了两种模拟方式,均出现类型错误:
方式一
// ... jest.mock("aws-sdk"); // ... const s3 = new AWS.S3() as jest.Mocked<S3>; s3.upload.mockResolvedValue({});
报错信息:
'Argument of type '{}' is not assignable to parameter of type 'never'
方式二
// ... // 模拟S3类及其upload方法 const mockUpload = jest.fn(); jest.mock('aws-sdk', () => { return { S3: jest.fn(() => ({ upload: mockUpload, })), }; }); // ... mockUpload.mockReturnValue({ promise: jest.fn().mockResolvedValue({ Location: "https://example-bucket.s3.amazonaws.com/filename.jpg", }), });
报错信息:
Argument of type '{ Location: string; }' is not assignable to parameter of type 'never'
注意:使用相同逻辑模拟
getSignedUrlPromise时无类型错误:const signedUrl = "https://signed-url.com/somefile.txt"; // 模拟签名URL生成 jest .spyOn(AWS.S3.prototype, "getSignedUrlPromise") .mockResolvedValue(signedUrl);
正确的模拟方案
方案1:使用jest.spyOn(推荐)
这种方式和getSignedUrlPromise的成功模拟逻辑一致,自动继承SDK类型,避免类型不匹配:
模拟upload方法
// 模拟upload返回的ManagedUpload对象及promise结果 jest.spyOn(AWS.S3.prototype, 'upload').mockReturnValue({ promise: jest.fn().mockResolvedValue({ Location: "https://example-bucket.s3.amazonaws.com/filename.jpg", Bucket: 'example-bucket', Key: 'filename.jpg', ETag: '"abc123"' }) } as AWS.S3.ManagedUpload);
模拟deleteObject方法
// 模拟deleteObject返回的Request对象及promise结果 jest.spyOn(AWS.S3.prototype, 'deleteObject').mockReturnValue({ promise: jest.fn().mockResolvedValue({}) } as AWS.S3.Request<AWS.S3.DeleteObjectOutput, AWS.AWSError>);
方案2:修正jest.mock的类型断言
如果需要整体模拟AWS SDK,需给mock对象添加正确的类型断言,确保符合S3类的结构:
import AWS from 'aws-sdk'; import { S3 } from 'aws-sdk'; jest.mock('aws-sdk', () => { const mockS3Instance = { upload: jest.fn().mockReturnValue({ promise: jest.fn().mockResolvedValue({ Location: "https://example-bucket.s3.amazonaws.com/filename.jpg" }) }), deleteObject: jest.fn().mockReturnValue({ promise: jest.fn().mockResolvedValue({}) }) }; return { S3: jest.fn(() => mockS3Instance as unknown as S3) }; }); // 测试用例中使用 const s3 = new AWS.S3(); // 断言方法调用 expect(s3.upload).toHaveBeenCalledWith(expect.objectContaining({ Bucket: bucketName, Key: filename }));
内容的提问来源于stack exchange,提问作者Hollow Dev
相关产品推荐
相关产品推荐

