【问题标题】:TypeError: AWS.SecretsManager is not a constructor in unit testing with proxyquireTypeError:AWS.SecretsManager 不是使用 proxyquire 进行单元测试的构造函数
【发布时间】:2021-12-14 04:48:55
【问题描述】:

我编写了一个测试代码来测试从 AWS Secret Manager 提供凭证的代码。我使用 proxyquire 和 sinon 来存根并得到这个错误。

我要测试的函数

    exports.getCredsFromAWSSecretsManager = (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;
    });
};

我写的测试用例

const sinon = require("sinon");
const proxyquire = require("proxyquire").noCallThru().noPreserveCache();
const { mockLogger } = require("../../mockdata/mockLogger");

let awsHelper;
let secretsManagerStub;

describe.only("AWS Helper ", () => {

    // function1

    describe("AWS Helper: getCredsFromAWSSecretsManagera method", () => {

        before((done) => {
            const data = {
                SecretString: JSON.stringify({ publicKey: 'secretUsername', privateKey: 'secretPassword' }),
              };
            
            secretsManagerStub = {
                getSecretValue: sinon.stub().callsFake((params, callback) => {
                  callback(null, data);
                }),
               
              };

            const awsStub = {
                
                  SecretsManager: sinon.stub().returns(secretsManagerStub)
               
                
            } 
            awsHelper = proxyquire('../../../utils/aws_helper.js', {
                'aws-sdk':{
                    AWS:awsStub
                } ,
                 "../../utils/logger": mockLogger,
            }); 
            
              

            done();
        });

        afterEach(() => {
            
            sinon.restore();
        });

        it('should write random data!', async () => {

            const expectedData = "abcdef";

            secretsManagerStub.getSecretValue.yields(null, expectedData);

            const data = await awsHelper.getCredsFromAWSSecretsManager();

            sinon.assert.callCount(secretsManagerStub.getSecretValue, 1);
            assert.strictEqual(data, expectedData);
            
        });

    });
});

这段代码给了我错误信息 TypeError:AWS.SecretsManager 不是构造函数

任何帮助将不胜感激。

【问题讨论】:

    标签: node.js unit-testing aws-sdk sinon proxyquire


    【解决方案1】:

    AWS 是一个命名空间,它包含所有 AWS 服务类,例如 SecretsManager。您应该将awsStub 提供给aws-sdk,无需将awsStub 包装在对象中。

    aws_helper.js:

    const AWS = require('aws-sdk');
    
    exports.getCredsFromAWSSecretsManager = () => {
      const SM = new AWS.SecretsManager({
        apiVersion: process.env.AWS_SM_API_VERSION,
        region: process.env.AWS_SM_REGION,
      });
      const params = {
        SecretId: '1',
      };
    
      return SM.getSecretValue(params)
        .promise()
        .then((data) => {
          console.info(data);
          return JSON.parse(data.SecretString);
        })
        .catch((err) => {
          console.error(err);
          throw err;
        });
    };
    

    aws_helper.test.js:

    const sinon = require('sinon');
    const proxyquire = require('proxyquire').noCallThru().noPreserveCache();
    
    let awsHelper;
    let secretsManagerStub;
    
    describe('AWS Helper: getCredsFromAWSSecretsManagera method', () => {
      before(() => {
        const data = {
          SecretString: JSON.stringify({ publicKey: 'secretUsername', privateKey: 'secretPassword' }),
        };
    
        secretsManagerStub = {
          getSecretValue: sinon.stub().returnsThis(),
          promise: sinon.stub().resolves(data),
        };
    
        const awsStub = {
          SecretsManager: sinon.stub().returns(secretsManagerStub),
        };
        awsHelper = proxyquire('./aws_helper.js', {
          'aws-sdk': awsStub,
        });
      });
    
      afterEach(() => {
        sinon.restore();
      });
    
      it('should write random data!', async () => {
        const data = await awsHelper.getCredsFromAWSSecretsManager();
        sinon.assert.callCount(secretsManagerStub.getSecretValue, 1);
        sinon.assert.match(data, { publicKey: 'secretUsername', privateKey: 'secretPassword' });
      });
    });
    

    测试结果:

      AWS Helper: getCredsFromAWSSecretsManagera method
    {
      SecretString: '{"publicKey":"secretUsername","privateKey":"secretPassword"}'
    }
        ✓ should write random data!
    
    
      1 passing (2s)
    
    ---------------|---------|----------|---------|---------|-------------------
    File           | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ---------------|---------|----------|---------|---------|-------------------
    All files      |   77.78 |      100 |   66.67 |   77.78 |                   
     aws_helper.js |   77.78 |      100 |   66.67 |   77.78 | 19-20             
    ---------------|---------|----------|---------|---------|-------------------
    

    【讨论】:

    • 非常感谢。现在可以了。我能知道我们为什么要在函数内部定义参数吗?有什么办法不改变功能代码。对不起,我不擅长 AWS 服务
    • @SanjanaEkanayake params?我没有从您的代码中看到此变量,因此我创建了一个以使代码可执行。重点是演示测试
    猜你喜欢
    • 2012-06-28
    • 1970-01-01
    • 2015-09-18
    • 1970-01-01
    • 2020-12-03
    • 1970-01-01
    • 2020-09-09
    • 2021-09-04
    • 1970-01-01
    相关资源
    最近更新 更多