使用proxyquire单元测试报错TypeError: AWS.SecretsManager is not a constructor
问题根因
- proxyquire 注入 aws-sdk 时的导出结构和实际业务代码引用的结构不匹配
- getSecretValue 桩方法的实现和业务代码的调用方式不兼容
具体原因说明
- 导出结构不匹配:正常业务代码中 aws-sdk 的引用方式是
const AWS = require('aws-sdk'),你在 proxyquire 配置里给aws-sdk导出的是{ AWS: awsStub },等于业务代码拿到的AWS变量外层多套了一层,自然找不到SecretsManager构造方法。 - 调用方式不兼容:业务代码调用
getSecretValue后用的是.promise()链式调用,你当前的桩方法是按回调模式实现的,没有返回带promise方法的对象,后续运行也会报错。 - 业务代码存在变量缺失:代码中使用的
params没有定义,本身就会抛出引用错误。
修复方案
第一步:修复业务代码
补充params变量定义:
exports.getCredsFromAWSSecretsManager = (keyName) => { // 补充params定义 const params = { SecretId: keyName }; const SM = new AWS.SecretsManager({ apiVersion: process.env.AWS_SM_API_VERSION, region: process.env.AWS_SM_REGION }); return SM.getSecretValue(params).promise().then((data) => { logger.info(logMsgs.awsHlpr_smGetSecretValueSuccess(JSON.stringify(data))); return JSON.parse(data.SecretString); }).catch((err) => { logger.error(logMsgs.awsHlpr_smGetSecretValueErr(JSON.stringify(err))); throw err; }); };
第二步:修改测试代码
调整proxyquire注入逻辑和桩方法实现:
const sinon = require("sinon"); const proxyquire = require("proxyquire").noCallThru().noPreserveCache(); const { mockLogger } = require("../../mockdata/mockLogger"); const assert = require('assert'); // 缺引入的话记得补充 let awsHelper; let secretsManagerStub; describe.only("AWS Helper ", () => { describe("AWS Helper: getCredsFromAWSSecretsManagera method", () => { before((done) => { const data = { SecretString: JSON.stringify({ publicKey: 'secretUsername', privateKey: 'secretPassword' }), }; secretsManagerStub = { // 适配.promise()调用的桩方法 getSecretValue: sinon.stub().returns({ promise: sinon.stub().resolves(data) }) }; const awsStub = { SecretsManager: sinon.stub().returns(secretsManagerStub) } // 修复aws-sdk的注入结构,直接导出awsStub awsHelper = proxyquire('../../../utils/aws_helper.js', { 'aws-sdk': awsStub, "../../utils/logger": mockLogger, }); done(); }); afterEach(() => { sinon.restore(); }); it('should return correct secret data', async () => { const expectedData = { publicKey: 'secretUsername', privateKey: 'secretPassword' }; const data = await awsHelper.getCredsFromAWSSecretsManager('test-key'); sinon.assert.callCount(secretsManagerStub.getSecretValue, 1); assert.deepStrictEqual(data, expectedData); }); }); });
内容的提问来源于stack exchange,提问作者Sanjana Ekanayake
相关产品推荐
相关产品推荐

