Testez la fonction asynchrone avec moka et sinon

Contexte

On me fait une petite fonction qui émet des messages via des sockets et j’essaye de le tester en utilisant mocha et sinon:

const myFun = socket => { socket.emit("first", "hello World!"); //some random amount of time passes socket.emit("second", "hello Moon!"); //other random amount of time passes socket.emit("third", "hello Mars? Venus? I dunno..."); }; 

En utilisant sinon je peux transmettre à ma fonction un fakeSocket:

 const fakeSocket = { emit: sinon.spy() }; 

Et vérifiez si j’émets ou non les messages.

Problème

Le problème ici est que je ne sais pas quand mon test se terminera . Parce que myFun ne myFun pas de promesse et que je n’ai pas de message final , je ne sais pas comment dire à mocha que j’ai envoyé tous les messages que je voulais et que le test devrait se terminer.

Tester

 const chai = require("chai"); const expect = chai.expect; const chaiAsPromised = require("chai-as-promised"); chai.use(chaiAsPromised); const sinon = require("sinon"); const sinonChai = require("sinon-chai"); chai.use(sinonChai); describe("myFun", () => { const fakeSocket = { emit: sinon.spy() }; it("receive first message", done => { myFun(fakeSocket); setTimeout(() => { try{ expect(fakeSocket.emit).to.have.been.calledThrice; done(); }catch(err){ done(err); } }, 1000); //1 seconds should be more than enough to let the test complete. }); }); 

J’utilise un setTimeout avec un try catch pour tester le code, ce qui est honnêtement assez horrible.

Question

  • Comment puis-je refaire mes tests afin de ne pas dépendre de setTimeout ?

Si vous savez qu’un message particulier est toujours défini en dernier, vous pouvez demander à Sinon d’appeler une fonction lorsque ce message est émis. Cette fonction peut être la fonction de rappel de Mocha pour les tests asynchrones:

 describe("myFun", function() { // Extend timeout and "slow test" values. this.timeout(3000).slow(10000); const fakeSocket = { emit: sinon.stub() } it('should emit a certain final message', done => { fakeSocket.emit.withArgs('third', 'hello Mars? Venus? I dunno...') .callsFake(() => done()); myFun(fakeSocket); }); }); 

Donc, si socket.emit() est appelé avec les arguments 'third', 'hello Mars?...' , Sinon appellera une fonction qui appelle le rappel done , signalant à Mocha que le test est terminé.

Lorsque, pour une raison quelconque, ce message n’est pas émis, done n’est jamais appelé et le test expire (au bout de 3 secondes), ce qui indique que le test a échoué ou qu’il a pris plus de temps que prévu.

Si vous ne savez pas ce que le premier argument de socket.emit() sera pour le dernier message, seul le message lui-même, le test devient ceci:

 it('should emit a certain final message', done => { fakeSocket.emit.callsFake((name, msg) => { if (msg === 'hello Mars? Venus? I dunno...') { done(); } }); myFun(fakeSocket); })