Sinon mock 正在调用真正的 AWS Secrets Manager

问题描述

我正在尝试模拟 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,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 不起作用?

解决方法

由于您在模块范围内实例化 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             
----------|---------|----------|---------|---------|-------------------

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...