Sinon.restore ne fonctionne pas pour le stubbing et le test des fonctions AWS
J'essaie donc d'écrire quelques tests pour tester une bibliothèque de wrapper AWS que j'ai écrite. Les tests s'exécutent individuellement sans aucun problème, mais ne s'exécutent pas tous comme un seul bloc «décrire».
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;
});
...
Ce que j'ai remarqué, c'est que dans le deuxième test, l'erreur que j'obtiens est sqs.receiveMessage is not a function
, ce qui signifie que le deuxième test utilise l' sqs
objet du premier test (je peux le vérifier davantage à mesure que l'erreur change si j'ajoute receiveMessage
au premier sqs
objet de test ).
Est-ce un bogue dans sinon restore, ou ai-je écrit quelque chose de manière incorrecte? Voici toute la bibliothèque:https://github.com/unegma/aws-utilities/blob/main/test/SQSTests.spec.js
Réponses
Ce n'est pas un problème avec Sinon. Il s'agit d'un problème lié à la façon dont vous stubbing AWS SDK. Décrivons ce qui se passe dans le code que vous avez partagé.
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;
Ce code fait ce qui suit
- Stub
SQS
deaws
. - Load
AWSUtilities.js
(basé sur le code source dans github)
AWSUtilities.js
fait ce qui suit dès qu'il est chargé
const aws = require('aws-sdk');
const sqs = new aws.SQS();
// code removed to demo the concept
Le code ci-dessus crée un sqs
objet interne , qui dans ce cas est créé à l'aide du module aws stubbed. Dans node une fois qu'un module est chargé en utilisant require
sa mémoire cache, c'est-à-dire que le code ci-dessus ne s'exécute qu'une seule fois.
Ainsi, lorsque le premier it()
s'exécute, il se charge à son tour AWSUtilities.js
pour la première fois et est mis en cache. Tous les appels ultérieurs obtiennent la version mise en cache. Lorsque vous l'appelez, sinon.restore
il ne restaure que la SQS
fonction du aws
module, il ne restaure pas l' sqs
objet qui a été créé à l'intérieur AWSUtilities.js
.
J'espère que cela explique la raison du comportement que vous voyez.
Il existe plusieurs façons de résoudre ce problème. Injection de dépendances, en utilisant des modules comme proxyquire, rewire, stubbing aws à partir d'un emplacement central avant tous les cas de test, etc.
Ce qui suit est une option pour résoudre ce problème uniquement dans les cas de test présentés ici.
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;
});
});