【问题标题】:Sinon mock is calling real AWS Secrets ManagerSinon mock 正在调用真正的 AWS Secrets Manager
【发布时间】:2021-07-23 03:10:41
【问题描述】:

我正在尝试模拟 AWS Secrets Manager 的 getSecretValue 方法。

它不起作用 - 它不是调用 sinon 模拟,而是调用真正的 AWS 函数。

示例测试:

'use strict';

const sinon = require( 'sinon' );
const AWS = require( 'aws-sdk' );
const secretsManager = new AWS.SecretsManager();
const unitUnderTest = require( '../modules/myUnitUnderTest' );
const { expect } = require( 'chai' );

describe( 'Failing example for Stack Overflow', async () => {

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

    it( 'mocks the call to AWS Secret Manager successfully', async () => {

        sinon.stub( secretsManager, 'getSecretValue' ).returns( Promise.resolve( {SecretString: { publicKey: 'secretUsername', privateKey: 'secretPassword' }} ) );
        const key = 'key';
        const username = null;
        const password = null;
        await unitUnderTest( key, username, password );
        expect( username ).to.equal( 'secretUsername' );
        expect( password ).to.equal( 'secretPassword' );
    } );
} );

示例函数:

const AWS = require( 'aws-sdk' );
const secretsManager = new AWS.SecretsManager();

module.exports = async ( keyId, username, password ) => {
        await getSecret( keyId )
            .then( secret => {
                username = secret.publicKey;
                password = secret.privateKey;
            } )
            .catch(
                err => {
                    logger.error( err );
                }
            );
};

const getSecret = (keyId ) => {
    return new Promise( ( resolve, reject ) => {
        secretsManager.getSecretValue( {
            SecretId: keyId
        }, ( err, data ) => {
            if ( err ) {
                reject( err );
            } else {
                resolve( JSON.parse( data.SecretString ) );
            }
        } );
    } );
};

预期行为:

Sinon 模拟 AWS Secrets Manager

实际行为:

Sinon 不起作用,AWS 被真正调用,我的日志中出现错误,证明真正的 AWS 开发工具包已被调用/已尝试从 AWS Secrets Manager 帐户中读取我在我的默认配置文件中的秘密机器:

Failed to obtain the secret: ConfigError: Missing region in config

我对此束手无策。为什么 sinon 不工作?

【问题讨论】:

    标签: node.js chai sinon aws-sdk-js aws-secrets-manager


    【解决方案1】:

    由于您在模块范围内实例化 AWS.SecretsManager,因此您需要在需要您的模块之前存根 AWS.SecretsManager 类。

    例如

    main.js:

    const AWS = require('aws-sdk');
    const secretsManager = new AWS.SecretsManager();
    
    module.exports = async (keyId) => {
      return getSecret(keyId)
        .then((secret) => {
          const username = secret.publicKey;
          const password = secret.privateKey;
          return { username, password };
        })
        .catch((err) => {
          console.error(err);
        });
    };
    
    const getSecret = (keyId) => {
      return new Promise((resolve, reject) => {
        secretsManager.getSecretValue(
          {
            SecretId: keyId,
          },
          (err, data) => {
            if (err) {
              reject(err);
            } else {
              resolve(JSON.parse(data.SecretString));
            }
          },
        );
      });
    };
    

    main.test.js:

    const AWS = require('aws-sdk');
    const sinon = require('sinon');
    const { expect } = require('chai');
    
    describe('67322634', () => {
      afterEach(() => {
        sinon.restore();
      });
      it('should get secret value', async () => {
        const data = {
          SecretString: JSON.stringify({ publicKey: 'secretUsername', privateKey: 'secretPassword' }),
        };
        const secretsManagerStub = {
          getSecretValue: sinon.stub().callsFake((params, callback) => {
            callback(null, data);
          }),
        };
        const SecretsManagerStub = sinon.stub(AWS, 'SecretsManager').returns(secretsManagerStub);
        const main = require('./main');
        const { username, password } = await main('1');
        expect(username).to.equal('secretUsername');
        expect(password).to.equal('secretPassword');
        sinon.assert.calledOnce(SecretsManagerStub);
        sinon.assert.calledOnceWithExactly(
          secretsManagerStub.getSecretValue,
          {
            SecretId: '1',
          },
          sinon.match.func,
        );
      });
    });
    

    单元测试结果:

      67322634
        ✓ should get secret value (1472ms)
    
    
      1 passing (1s)
    
    ----------|---------|----------|---------|---------|-------------------
    File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ----------|---------|----------|---------|---------|-------------------
    All files |   85.71 |       50 |   83.33 |   85.71 |                   
     main.js  |   85.71 |       50 |   83.33 |   85.71 | 12,24             
    ----------|---------|----------|---------|---------|-------------------
    

    【讨论】:

    • Arrgh 范围界定!谢谢你这么清楚的回答
    猜你喜欢
    • 2022-11-08
    • 2018-09-10
    • 2020-04-07
    • 2022-09-23
    • 2020-08-23
    • 1970-01-01
    • 1970-01-01
    • 2019-08-30
    • 2019-06-11
    相关资源
    最近更新 更多