AWS 함수 스터 빙 및 테스트에 대해 Sinon.restore가 작동하지 않음
그래서 저는 제가 작성한 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;
이 코드는 다음을 수행합니다.
- 스텁
SQS
의aws
. - 로드
AWSUtilities.js
(github의 소스 코드 기반)
AWSUtilities.js
로드되는 즉시 다음을 수행합니다.
const aws = require('aws-sdk');
const sqs = new aws.SQS();
// code removed to demo the concept
위의 코드는 내부 sqs
객체를 생성하며 ,이 경우에는 stubbed aws 모듈을 사용합니다. 노드에서 모듈이로드되면 require
메모리에 캐시됩니다. 즉, 위 코드는 한 번만 실행됩니다.
따라서 첫 번째가 it()
실행 되면 처음 으로로드 AWSUtilities.js
되고 캐시됩니다. 모든 후속 호출은 캐시 된 버전을 가져옵니다. 호출 sinon.restore
하면 모듈 의 SQS
기능 만 복원하고 .NET에서 생성 된 객체는 aws
복원하지 않습니다 .sqs
AWSUtilities.js
나는 그것이 당신이보고있는 행동의 이유를 설명하기를 바랍니다.
이 문제를 해결하는 방법에는 여러 가지가 있습니다. 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;
});
});