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

NodeJS中如何Mock AWS SDK的Promise调用?

解决AWS SDK Mock describeAccountAttributes Promise调用的问题

我看了你的代码,主要有几个关键问题导致mock没生效,下面一步步给你拆解和修正:

1. 业务代码的核心问题:模块加载时提前执行了API调用

你的业务代码里,getAccountAttributes是在模块加载阶段就直接调用了ec2.describeAccountAttributes(PARAMS_ACCOUNT).promise(),这时候测试代码还没来得及mock AWS SDK的方法。当测试用例运行时,这个Promise已经发起了真实的请求(或者因为没配置AWS凭证报错),mock根本拦截不到。

修正后的业务代码:
把API调用放到函数内部,而不是模块顶层,这样每次调用maxInstances时才会触发API请求,给mock留足时间:

const AWS = require('aws-sdk');
const PARAMS_ACCOUNT = {
  AttributeNames: [
     "max-instances"
  ]
};

// 不要在这里提前初始化Promise
const ec2 = new AWS.EC2();

function maxInstances() {
    // 每次调用函数时才发起API请求
    return ec2.describeAccountAttributes(PARAMS_ACCOUNT).promise()
        .then(data => {
            return data.AccountAttributes[0].AttributeValues[0].AttributeValue;
        });
}

// 记得导出函数,假设你原来的文件是instance_limit.js
module.exports = { maxInstances };

2. 测试代码的问题:异步测试未处理 + Mock时机/方式问题

你的测试代码有两个关键问题:

  • maxInstances返回的是Promise,你用同步的expect(instances).to.equal(10)肯定不对,Mocha需要处理异步测试(用async/await或者done回调)
  • Mock的时机:你应该在测试用例之前就mock好AWS SDK,并且测试结束后要恢复mock,避免影响其他用例

修正后的测试代码:

const chai = require('chai');
const awsSDK = require('aws-sdk');
const awsMock = require('aws-sdk-mock');
const { maxInstances } = require('../instance_limit.js');

const expect = chai.expect;

describe('Sample test', () => {
    // 在每个测试用例前mock,测试后恢复
    beforeEach(() => {
        awsMock.mock('EC2', 'describeAccountAttributes', (params, callback) => {
            callback(null, {
                AccountAttributes: [{
                    AttributeValues: [{ AttributeValue: 10 }]
                }]
            });
        });
    });

    afterEach(() => {
        awsMock.restore('EC2'); // 恢复mock,避免污染其他测试
    });

    it('should return the mocked max instances count', async () => {
        // 用async/await处理异步Promise
        const instances = await maxInstances();
        expect(instances).to.equal(10);
    });
});

额外优化:适配Promise的Mock写法

如果你更喜欢用Promise风格的mock(而不是回调),aws-sdk-mock也支持,这样写更贴合业务代码里的.promise()调用风格:

awsMock.mock('EC2', 'describeAccountAttributes', Promise.resolve({
    AccountAttributes: [{
        AttributeValues: [{ AttributeValue: 10 }]
    }]
}));

为什么原来的代码不生效?

  • 模块加载顺序问题:业务代码在测试代码require的时候就执行了describeAccountAttributes,这时候mock还没设置,请求直接走了真实的AWS SDK
  • 异步未处理问题:Promise是异步的,同步断言的时候Promise还没resolve,你拿到的是Promise对象而不是预期的10,断言自然失败

这样调整后,你的mock就能正常拦截API调用,测试也能正确断言结果了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:11:32