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(); }); });
你之前测试失败的核心原因
- 同时混用
aws-sdk-mock和Jest的spyOn,两种mock机制冲突,导致mock未生效 s3.spyOn('S3', 'getObject')写法错误,spyOn的第一个参数必须是对象(如AWS.S3.prototype),而非字符串- 业务代码中bucket是硬编码字符串,未使用传入的event参数,导致测试event无效
- mock返回结构不符合S3规范:
s3.getObject().promise()需要返回包含Body的对象,你之前的mock未正确模拟promise的返回结构
内容的提问来源于stack exchange,提问作者Lucky
相关产品推荐
相关产品推荐

