如何解决Sinon.restore() 不适用于命名空间类的继承函数
Node AWS SDK 有一个名为 AWS
的命名空间,其中包含一个名为 SecretsManager
的类。 SecretsManager
继承了一个名为 getSecretValue
的函数定义。
我想在两个单独的单元测试中用两种不同的结果存根 AWS Secret Manager 的 getSecretValue
方法。
我编写了两个单独的单元测试,它们单独运行良好,但一起运行时失败。
sinon.restore()
不起作用。
测试代码:
const AWS = require( 'aws-sdk' );
const sinon = require( 'sinon' );
const { expect } = require( 'chai' );
describe( '67672805',() => {
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,);
} );
it( 'should not get secret value if there is an error with SecretsManager',async () => {
const secretsManagerStub = {
getSecretValue: sinon.stub().callsFake( ( params,callback ) => {
const err = new Error( 'There was an error' );
callback( err );
} ),password } = await main( '1' );
expect( username ).to.not.equal( 'secretUsername' );
expect( password ).to.not.equal( 'secretPassword' );
sinon.assert.calledOnce( SecretsManagerStub );
sinon.assert.calledOnceWithExactly(
secretsManagerStub.getSecretValue,);
} );
} );
驱动程序代码:
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 ) );
}
},);
} );
};
Package.json:
"aws-sdk": "2.894.0","chai": "4.3.4","sinon": "10.0.0"
预期:sinon.restore() 有效
实际:sinon.restore() 未正确重置 - 第二个单元测试失败,因为它使用在第一个单元测试中设置的相同存根。如果您颠倒测试顺序,它们就会以相反的方式失败。如果您单独运行测试,它们就会通过。
这有什么问题吗?文档表明这应该没问题。
解决方法
@fatso83 在 Sinon github 页面上回答了这个问题:https://github.com/sinonjs/sinon/issues/2376#issuecomment-847258040 并花时间在此处发布此问题的分支及其解决方案:https://github.com/fatso83/sinon-2376
此问题是由范围引起的。而不是在 main.js
顶部的模块范围内声明 AWS 秘密管理器:
const AWS = require( 'aws-sdk' );
const secretsManager = new AWS.SecretsManager(); // module scope
存根项应该在函数范围内声明,如下所示:
const getSecret = ( keyId ) => {
return new Promise( ( resolve,reject ) => {
const secretsManager = new AWS.SecretsManager() // function scope
secretsManager.getSecretValue(
{
SecretId: keyId,},( err,data ) => {
if ( err ) {
reject( err );
} else {
resolve( JSON.parse( data.SecretString ) );
}
},);
这会导致测试通过,因为 AWS Secrets Manager 的模块范围实例不会在测试调用之间保留(而是在每次调用函数时由新的函数范围实例替换)。
TLDR:不要使用 SinonJS 来存根模块范围的依赖项。
感谢@fatso83
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。