简体   繁体   中英

Sinon mock is calling real AWS Secrets Manager

I am trying to mock the getSecretValue method of AWS Secrets Manager.

It is not working - instead of calling the sinon mock, it calls the real AWS function.

Example test:

'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' );
    } );
} );

Example function:

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 ) );
            }
        } );
    } );
};

Expected behaviour:

Sinon mocks AWS Secrets Manager

Actual behaviour:

Sinon doesn't work, AWS is called for real and I get errors in my logs proving that the real AWS SDK has been invoked/has tried to read a secret out of an AWS Secrets Manager account for my default profile on my machine:

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

I am at my wits end with this. Why is sinon not working?

Since you are instantiating AWS.SecretsManager at module scope, you need to stub the AWS.SecretsManager class before requiring your module.

Eg

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,
    );
  });
});

unit test result:

  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             
----------|---------|----------|---------|---------|-------------------

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM