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

Jest测试中如何让S3.getObject返回模拟值(TypeScript环境)

正确模拟S3.getObject的解决方案

先提下业务代码里的关键问题(不修正的话测试传的event参数会无效):
你业务代码里const bucket = 'event.s3.bucket.name';是硬编码字符串,没有从传入的event中取值,应该改成:

const bucket = event.Records[0].s3.bucket.name;
const filename = event.Records[0].s3.object.key;

下面给两种可行的mock方案,选一种即可,不要混用:

方案一:使用aws-sdk-mock(更简洁省心)

调整测试代码如下:

import { getFileContent } from "../../utils/FileContent";
const lambdaHandler = require('../lambda/myLambda');
const AWSMock = require('aws-sdk-mock');
const AWS = require("aws-sdk");

// 绑定AWS实例给mock工具
AWSMock.setSDKInstance(AWS);

describe('my handler test', () => {
  // 每个测试前重置mock,避免测试间污染
  beforeEach(() => AWSMock.reset());

  test('s3 getObject返回预设模拟值', async () => {
    const mockFileData = getFileContent('fileName.csv');
    
    // 模拟S3.getObject方法,按S3回调格式返回结果
    AWSMock.mock('S3', 'getObject', (params, callback) => {
      // 可选:验证调用参数是否符合预期
      expect(params.Bucket).toBe('test-bucket');
      expect(params.Key).toBe('test-filename');
      // 第一个参数为null代表无错误,第二个参数是返回结果
      callback(null, { Body: mockFileData });
    });

    // 构造符合业务逻辑的测试event
    const testEvent = {
      Records: [
        {
          s3: {
            bucket: { name: 'test-bucket' },
            object: { key: 'test-filename' }
          }
        }
      ]
    };

    // 执行handler
    await lambdaHandler.handler(testEvent, {}, () => {});

    // 这里可以添加业务逻辑相关断言,比如验证getFileContents是否被正确调用等
  });
});

方案二:使用Jest原生SpyOn(无需额外依赖)

如果不想用aws-sdk-mock,直接用Jest自带的spyOn:

import { getFileContent } from "../../utils/FileContent";
const lambdaHandler = require('../lambda/myLambda');
const AWS = require("aws-sdk");

describe('my handler test', () => {
  test('s3 getObject返回预设模拟值', async () => {
    const mockFileData = getFileContent('fileName.csv');
    
    // 给S3原型的getObject方法添加spy,模拟返回带promise的对象
    const getObjectSpy = jest.spyOn(AWS.S3.prototype, 'getObject').mockReturnValue({
      promise: jest.fn().mockResolvedValue({ Body: mockFileData })
    });

    // 构造符合业务逻辑的测试event
    const testEvent = {
      Records: [
        {
          s3: {
            bucket: { name: 'test-bucket' },
            object: { key: 'test-filename' }
          }
        }
      ]
    };

    // 执行handler
    await lambdaHandler.handler(testEvent, {}, () => {});

    // 验证getObject是否被正确调用
    expect(getObjectSpy).toHaveBeenCalledWith({
      Bucket: 'test-bucket',
      Key: 'test-filename'
    });

    // 恢复spy,避免影响其他测试
    getObjectSpy.mockRestore();
  });
});

你之前测试失败的核心原因

  1. 同时混用aws-sdk-mock和Jest的spyOn,两种mock机制冲突,导致mock未生效
  2. s3.spyOn('S3', 'getObject')写法错误,spyOn的第一个参数必须是对象(如AWS.S3.prototype),而非字符串
  3. 业务代码中bucket是硬编码字符串,未使用传入的event参数,导致测试event无效
  4. mock返回结构不符合S3规范:s3.getObject().promise()需要返回包含Body的对象,你之前的mock未正确模拟promise的返回结构

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 23:10:43