Sinon mock 正在调用真正的 AWS Secrets Manager
Sinon mock is calling real 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, 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 SDK 已被 invoked/has 尝试从 AWS Secrets Manager 帐户中读取我的秘密我机器上的默认配置文件:
Failed to obtain the secret: ConfigError: Missing region in config
我对此束手无策。为什么 sinon 不工作?
由于您是在模块范围内实例化 AWS.SecretsManager
,因此您需要在需要模块之前对 AWS.SecretsManager
class 进行存根。
例如
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
----------|---------|----------|---------|---------|-------------------
我正在尝试模拟 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 SDK 已被 invoked/has 尝试从 AWS Secrets Manager 帐户中读取我的秘密我机器上的默认配置文件:
Failed to obtain the secret: ConfigError: Missing region in config
我对此束手无策。为什么 sinon 不工作?
由于您是在模块范围内实例化 AWS.SecretsManager
,因此您需要在需要模块之前对 AWS.SecretsManager
class 进行存根。
例如
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
----------|---------|----------|---------|---------|-------------------