You need to enable JavaScript to run this app. 如何用Jest正确mock S3的createPresignedPost方法
优惠活动
大模型
产品
解决方案
定价
更多

如何用Jest正确mock S3的createPresignedPost方法

问题原因

  • 参数多出匿名函数:AWS.S3.createPresignedPost本身接收两个入参,第一个是配置对象,第二个是执行完成后的回调函数。原测试断言只校验了第一个配置参数,没有将第二个回调参数纳入预期,因此触发参数不匹配报错。
  • 无法正常await调用:
    1. 原测试用例注释掉了async修饰符和await关键字
    2. 原mock实现不符合接口的实际调用逻辑:createPresignedPost是回调风格API,本身不返回带promise()方法的对象,需要让mock主动触发传入的回调,才能让业务函数外层包裹的Promise正常决议,await才不会卡住。

修复后的测试代码

const createPresignedPost = require('./你的业务文件路径');

const mockedCreatePresignedPost = jest.fn((params, callback) => {
  // 模拟调用成功,触发回调返回模拟数据
  callback(null, {
    url: 'https://mock-s3-url.com',
    fields: { mockKey: 'mockValue' }
  });
});

jest.mock('aws-sdk', () => {
  return {
    S3: jest.fn(() => ({
      createPresignedPost: mockedCreatePresignedPost
    })),
    config: {
      update: jest.fn()
    }
  };
});

// 加async修饰符
it('has to mock S3#createPresignedPost', async () => {
  process.env.AWS_BUCKET_NAME = 'test1';
  const params = {
    key: 'test2',
    contentType: 'application/json'
  };
  const s3params = {
    Bucket: 'test1',
    Conditions: [['content-length-range', 100, 10000000]],
    Expires: 60,
    Fields: {
      'Access-Control-Allow-Origin': '*',
      'Cache-Control': 'max-age=31536000',
      'Content-Type': params['contentType'],
      key: params['key']
    }
  };
  // 加await调用
  const result = await createPresignedPost(params);
  // 断言时加入第二个回调参数的匹配,用expect.any(Function)匹配任意函数
  expect(mockedCreatePresignedPost).toHaveBeenCalledWith(s3params, expect.any(Function));
  // 可选:断言返回结果符合预期,提升覆盖率
  expect(result).toEqual({
    url: 'https://mock-s3-url.com',
    fields: { mockKey: 'mockValue' }
  });
});

核心修改说明

  1. 调整mockedCreatePresignedPost的实现:接收到传入的回调函数后主动触发,模拟接口调用成功的逻辑,保证外层Promise可以正常决议
  2. 给测试用例加async修饰符,调用业务函数时加await,解决异步调用问题
  3. 断言参数时加入expect.any(Function)匹配第二个回调参数,消除参数不匹配报错
  4. 额外增加返回结果的断言,可以覆盖业务函数中Promise resolve的分支,进一步提升测试覆盖率,满足CI阈值要求

可选:覆盖错误分支(进一步提升覆盖率)

如果需要覆盖接口报错的reject分支,可以新增如下测试用例:

it('handles S3 createPresignedPost error', async () => {
  const mockError = new Error('S3 service error');
  mockedCreatePresignedPost.mockImplementationOnce((params, callback) => {
    callback(mockError);
  });
  await expect(createPresignedPost({ key: 'test', contentType: 'text/plain' })).rejects.toThrow(mockError);
});

内容的提问来源于stack exchange,提问作者Igor Shmukler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 06:18:02