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
相关产品推荐
相关产品推荐

