Sinon.restoreがAWS関数のスタブとテストで機能しない
そのため、私が作成しているAWSラッパーライブラリをテストするためのいくつかのテストを作成しようとしています。テストは問題なく個別に実行されますが、すべてが1つの「describe」ブロックとして実行されるわけではありません。
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;
});
...
私が気付いたのは、2番目のテストで得られるエラーはですsqs.receiveMessage is not a function
。これは、2番目のテストがsqs
最初のテストのオブジェクトを使用していることを意味します(receiveMessage
最初のテストsqs
オブジェクトに追加するとエラーが変化するため、これをさらに確認できます) )。
これはsinon復元のバグですか、それとも間違って書いたのですか?ライブラリ全体は次のとおりです。https://github.com/unegma/aws-utilities/blob/main/test/SQSTests.spec.js
回答
これはSinonの問題ではありません。これは、AWSSDKをスタブする方法の問題です。共有したコード内で何が起こっているかを分析してみましょう。
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
オブジェクトを作成します。この場合、これはスタブされたawsモジュールを使用して作成されます。ノードでは、モジュールがrequire
メモリにキャッシュされていることを使用してロードされると、上記のコードは1回だけ実行されます。
したがって、最初にit()
実行すると、順番にロードさAWSUtilities.js
れ、キャッシュされます。以降の呼び出しでは、キャッシュされたバージョンが取得されます。これを呼び出すsinon.restore
とSQS
、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;
});
});