如何用Jest模拟aws-sdk?仅模拟单个函数的实现方案
如何用Jest仅模拟AWS SDK的单个函数
我来帮你梳理下问题所在,以及如何正确实现你的需求。首先看你当前的代码,主要有两个核心问题:一是没有正确模拟AWS SDK方法的promise()调用,二是断言的对象不对(你要断言的是实例方法,不是类方法)。
问题拆解
你的handler.js里调用了secretsManager.describeSecret().promise()和secretsManager.getSecretValue().promise(),但你之前的mock只返回了空对象,没有包含promise()方法,这会导致代码运行时直接报错。另外,你断言的aws.SecretsManager.getSecretManager不仅拼写错误,而且方向错了——getSecretValue是实例对象的方法,不是SecretsManager类本身的方法。
正确的实现方式
下面是修改后的测试代码,我会一步步解释关键点:
'use strict'; const aws = require('aws-sdk'); const { handler } = require('../../src/rotateSecret/index'); jest.mock('aws-sdk'); // 1. 先创建单独的mock函数,方便后续断言 const mockDescribeSecret = jest.fn().mockReturnThis(); const mockGetSecretValue = jest.fn().mockReturnThis(); const mockPromise = jest.fn(); // 2. 配置SecretsManager的mock构造函数,让new出来的实例包含需要的方法 aws.SecretsManager.mockImplementation(() => ({ describeSecret: mockDescribeSecret, getSecretValue: mockGetSecretValue, promise: mockPromise })); const event = { SecretId: 'test', ClientRequestToken: 'ccc', Step: 'createSecret', }; describe('rotateSecret', () => { // 3. 每个测试前清空mock的调用记录,避免测试间互相影响 beforeEach(() => { mockDescribeSecret.mockClear(); mockGetSecretValue.mockClear(); mockPromise.mockClear(); }); it('should not call getSecretValue when conditions are not met', async () => { // 4. 模拟describeSecret的返回值,让handler里的someCondition不成立 // 根据你的业务逻辑调整返回内容,确保代码走到return分支 mockPromise.mockResolvedValue({ /* 比如返回让someCondition为false的数据,例如:rotationEnabled: false */ }); await handler(event); // 5. 正确断言:describeSecret被调用,getSecretValue没被调用 expect(mockDescribeSecret).toHaveBeenCalledWith({ SecretId: event.SecretId }); expect(mockGetSecretValue).not.toHaveBeenCalled(); }); });
关键说明
- 模拟promise调用:AWS SDK的方法返回的是一个Request对象,必须调用
.promise()才能获取异步结果,所以我们的mock方法需要返回this(通过mockReturnThis()),保证链式调用能找到promise方法。 - 单独管理mock函数:把
describeSecret、getSecretValue和promise都做成独立的jest mock函数,这样可以精准控制返回值,也方便后续做调用断言。 - 测试隔离:用
beforeEach清空mock的调用记录,确保每个测试用例的mock状态都是干净的。 - 精准控制业务分支:通过
mockPromise.mockResolvedValue()返回特定数据,让代码走到你要测试的分支(也就是不调用getSecretValue的分支)。
如果只想模拟单个函数(其他用真实实现)
如果你的需求是只模拟getSecretValue,而让describeSecret保持真实调用(不推荐,测试应该尽量隔离外部依赖),可以这样调整:
// 创建一个包含真实describeSecret和mock getSecretValue的实例 const mockSecretsManagerInstance = { describeSecret: aws.SecretsManager.prototype.describeSecret, // 使用真实方法 getSecretValue: jest.fn().mockReturnThis(), promise: jest.fn().mockResolvedValue({}) }; // 让SecretsManager构造函数返回这个实例 aws.SecretsManager.mockImplementation(() => mockSecretsManagerInstance);
内容的提问来源于stack exchange,提问作者user1283776
相关产品推荐
相关产品推荐

