Sinon.restore funktioniert nicht zum Stubben und Testen von AWS-Funktionen
Ich versuche also, ein paar Tests zum Testen einer AWS-Wrapper-Bibliothek zu schreiben, die ich geschrieben habe. Die Tests werden einzeln ohne Probleme ausgeführt, aber nicht alle werden als ein "Beschreibungsblock" ausgeführt.
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;
});
...
Was ich aufgefallen ist, dass in dem zweiten Test, der Fehler I bin immer sqs.receiveMessage is not a function
, was bedeutet , dass der zweite Test des verwendete sqs
Objekt aus dem ersten Test (ich dies als Fehler Änderungen weiter verifizieren kann , wenn ich hinzufügen , receiveMessage
mit dem ersten sqs
Testobjekt ).
Ist dies ein Fehler bei der Sinon-Wiederherstellung oder habe ich etwas falsch geschrieben? Hier ist die ganze Bibliothek:https://github.com/unegma/aws-utilities/blob/main/test/SQSTests.spec.js
Antworten
Dies ist kein Problem mit Sinon. Dies ist eine Frage, wie Sie das AWS SDK stubben. Lassen Sie uns zusammenfassen, was in dem von Ihnen freigegebenen Code passiert.
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;
Dieser Code führt Folgendes aus
- Stummel
SQS
vonaws
. - Laden
AWSUtilities.js
(basierend auf dem Quellcode in Github)
AWSUtilities.js
führt Folgendes aus, sobald es geladen ist
const aws = require('aws-sdk');
const sqs = new aws.SQS();
// code removed to demo the concept
Der obige Code erstellt ein internes sqs
Objekt, das in diesem Fall mit dem stubbed aws-Modul erstellt wird. Sobald ein Modul im Knoten geladen wurde, wird require
es im Speicher zwischengespeichert, dh der obige Code wird nur einmal ausgeführt.
Wenn der erste it()
ausgeführt wird, wird er wiederum AWSUtilities.js
zum ersten Mal geladen und zwischengespeichert. Alle nachfolgenden Aufrufe erhalten die zwischengespeicherte Version. Wenn Sie es aufrufen sinon.restore
, wird nur die SQS
Funktion des aws
Moduls wiederhergestellt, und das darin erstellte sqs
Objekt wird nicht wiederhergestellt AWSUtilities.js
.
Ich hoffe, das erklärt den Grund für das Verhalten, das Sie sehen.
Es gibt mehrere Möglichkeiten, um dieses Problem zu beheben. Abhängigkeitsinjektion unter Verwendung von Modulen wie Proxyquire, Neuverdrahtung, Stubbing von Aws von einer zentralen Stelle vor allen Testfällen usw.
Das Folgende ist eine Option, um das Problem nur in den hier gezeigten Testfällen zu beheben.
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;
});
});