You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 19:57:25