Reputation: 17584
I am made a small function that emits messages via sockets and I am trying to test it using mocha and 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...");
};
Using sinon I can pass to my function a fakeSocket:
const fakeSocket = {
emit: sinon.spy()
};
And check if I emit or not the messages.
The problem here is that I don't know when my test ends. Because myFun
does not return a promise and I don't have a final message I don't know how to tell mocha that I have sent all the messages I wanted and that the test should end.
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.
});
});
I am using a setTimeout
with a try catch
to test the code, which honestly is quite horrible.
setTimeout
?Upvotes: 0
Views: 1208
Reputation: 203484
If you know that a particular message is always set last, you can instruct Sinon to call a function when that message is emitted. That function can be Mocha's callback function for asynchronous tests:
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);
});
});
So if socket.emit()
is called with arguments 'third', 'hello Mars?...'
, Sinon will call a function that calls the done
callback, signalling to Mocha that the test has completed.
When, for some reason, that particular message isn't emitted, done
never gets called and the test will time out (after 3s), which is an indication that either the test has failed, or it took more time than expected.
If you don't know what the first argument to socket.emit()
is going to be for the last message, only the message itself, the test becomes this:
it('should emit a certain final message', done => {
fakeSocket.emit.callsFake((name, msg) => {
if (msg === 'hello Mars? Venus? I dunno...') {
done();
}
});
myFun(fakeSocket);
})
Upvotes: 1