Sinon.restore不适用于存根和测试AWS功能



因此,我正在尝试编写一些测试,以测试我一直在编写的AWS包装库。测试是单独运行的,没有任何问题,但不会全部作为一个"描述"块运行。

const AWS_REGION = 'eu-west-2';
const aws = require('aws-sdk');
const chai = require('chai');
const expect = chai.expect;
const sinon = require('sinon');
const sinonChai = require('sinon-chai');
chai.use(sinonChai);
// These help:
// https://stackoverflow.com/questions/26243647/sinon-stub-in-node-with-aws-sdk
// https://stackoverflow.com/questions/61516053/sinon-stub-for-lambda-using-promises
describe('SQS Utilities Test', () => {
afterEach(() => {
sinon.restore();
});
it('should add to SQS', async () => {
sinon.stub(aws.config, 'update');
const sqs = {
sendMessage: sinon.stub().returnsThis(),
promise: sinon.stub()
};
sinon.stub(aws, 'SQS').callsFake(() => sqs);
// these use the above stubbed version of aws
const AWSUtilities = require('../index').AWSUtilities;
const awsUtilities = new AWSUtilities(AWS_REGION);
const response = await awsUtilities.postToSQS('https://example.com', { id: 1}, 'chicken');
expect(sqs.sendMessage).to.have.been.calledOnce;
});
it('should get from SQS', async () => {
sinon.stub(aws.config, 'update');
const sqs = {
receiveMessage: sinon.stub().returnsThis(),
promise: sinon.stub()
};
sinon.stub(aws, 'SQS').callsFake(() => sqs);
// these use the above stubbed version of aws
const AWSUtilities = require('../index').AWSUtilities;
const awsUtilities = new AWSUtilities(AWS_REGION);
const response = await awsUtilities.getFromSQS('https://example.com');
expect(sqs.receiveMessage).to.have.been.calledOnce;
});
...

我注意到,在第二次测试中,我得到的错误是sqs.receiveMessage is not a function,这意味着第二次检测使用的是第一次检测中的sqs对象(如果我将receiveMessage添加到第一次检测sqs对象中,错误会发生变化,我可以进一步验证这一点(。

这是sinon恢复中的错误,还是我写错了什么?这是整个图书馆:https://github.com/unegma/aws-utilities/blob/main/test/SQSTests.spec.js

这不是Sinon的问题。这是一个如何清除AWS SDK的问题。让我们来分析一下您共享的代码中发生了什么。

const sqs = {
sendMessage: sinon.stub().returnsThis(),
promise: sinon.stub()
};
sinon.stub(aws, 'SQS').callsFake(() => sqs);
// these use the above stubbed version of aws
const AWSUtilities = require('../index').AWSUtilities;

此代码执行以下

  1. aws的短截线SQS
  2. 加载AWSUtilities.js(基于github中的源代码(

AWSUtilities.js在加载后立即执行以下操作

const aws = require('aws-sdk');
const sqs = new aws.SQS();
// code removed to demo the concept

上面的代码创建了一个内部sqs对象,在本例中,该对象是使用存根aws模块创建的。在节点中,一旦使用require加载模块,它就会缓存在内存中,即上面的代码只执行一次。

因此,当第一个it()执行时,它依次第一次加载AWSUtilities.js并被缓存。任何后续调用都会获取缓存的版本。当您调用sinon.restore时,它只恢复aws模块的SQS函数,而不恢复在AWSUtilities.js中创建的sqs对象。

我希望这能解释你所看到的行为的原因。

有多种方法可以解决此问题。依赖注入,使用proxyquire、rewire等模块,在所有测试用例之前从中心位置清除aws等。

以下是在这里显示的测试用例中修复它的选项。

describe('SQS Utilities Test', () => {
let AWSUtilities, sqsStub;
before(() => {
sinon.stub(aws.config, 'update');
sqsStub = {
sendMessage: sinon.stub().returnsThis(),
receiveMessage: sinon.stub().returnsThis(),
promise: sinon.stub()
};
sinon.stub(aws, 'SQS').callsFake(() => sqs);
AWSUtilities = require('../index').AWSUtilities;
});
after(() => {
sinon.restore();
});
it('should add to SQS', async () => {
const awsUtilities = new AWSUtilities(AWS_REGION);
const response = await awsUtilities.postToSQS('https://example.com', { id: 1}, 'chicken');
expect(sqsStub.sendMessage).to.have.been.calledOnce;
});
it('should get from SQS', async () => {
const awsUtilities = new AWSUtilities(AWS_REGION);
const response = await awsUtilities.getFromSQS('https://example.com');
expect(sqsStub.receiveMessage).to.have.been.calledOnce;
});
});

最新更新