I'm writing a bunch of mocha tests and I'd like to test that particular events are emitted. Currently, I'm doing this:
it('should emit an some_event', function(done){
myObj.on('some_event',function(){
assert(true);
done();
});
});
However, if the event never emits, it crashes the test suite rather than failing that one test.
What's the best way to test this?
If you can guarantee that the event should fire within a certain amount of time, then simply set a timeout.
it('should emit an some_event', function(done){
var errTimeout = setTimeout(function () {
assert(false, 'Event never fired'); //or assert.fail, or whatever.
done(); //I don't remember whether or not you still supposed to call done()
}, 1000); //timeout with an error in one second
myObj.on('some_event',function(){
clearTimeout(errTimeout); //cancel error timeout
assert(true);
done();
});
});
Make sure your timeout setting in Mocha is at least as high as the timeout you use in the code here.
If you can't guarantee when the event will fire, then it might not be a good candidate for unit testing.
Edit Sept 30:
I see my answer is accepted as the right answer, but Bret Copeland's technique (see answer below) is simply better because it's faster for when the test is successful, which will be the case most times you run a test as part of a test suite.
Bret Copeland's technique is correct. You can also do it a bit differently:
it('should emit an some_event', function(done){
var eventFired = false
setTimeout(function () {
assert(eventFired, 'Event did not fire in 1000 ms.');
done();
}, 1000); //timeout with an error in one second
myObj.on('some_event',function(){
eventFired = true
});
// do something that should trigger the event
});
This can be made a little shorter with help of Sinon.js.
it('should emit an some_event', function(done){
var eventSpy = sinon.spy()
setTimeout(function () {
assert(eventSpy.called, 'Event did not fire in 1000ms.');
assert(eventSpy.calledOnce, 'Event fired more than once');
done();
}, 1000); //timeout with an error in one second
myObj.on('some_event',eventSpy);
// do something that should trigger the event
});
Here we're checking that not only has the event fired, but also if if event has fired only once during the time-out period.
Sinon also supports calledWith and calledOn, to check what arguments and function context was used.
Note that if you expect the event to be triggered synchronously with the operation that triggered the event (no async calls in between) then you can do with a timeout of zero. A timeout of 1000 ms is only necessary when you do async calls in between which take a long time to complete. Most likely not the case.
Actually, when the event is guaranteed to fire synchronously with the operation that caused it, you could simplify the code to
it('should emit an some_event', function() {
eventSpy = sinon.spy()
myObj.on('some_event',eventSpy);
// do something that should trigger the event
assert(eventSpy.called, 'Event did not fire.');
assert(eventSpy.calledOnce, 'Event fired more than once');
});
Otherwise, Bret Copeland's technique is always faster in the "success" case (hopefully the common case), since it's able to immediately call done if the event is triggered.
Just stick:
this.timeout(<time ms>);
at the top of your it statement:
it('should emit an some_event', function(done){
this.timeout(1000);
myObj.on('some_event',function(){
assert(true);
done();
});`enter code here`
});
Late to the party here, but I was facing exactly this problem and came up with another solution. Bret's accepted answer is a good one, but I found that it wreaked havoc when running my full mocha test suite, throwing the error done() called multiple times, which I ultimately gave up trying to troubleshoot. Meryl's answer set me on the path to my own solution, which also uses sinon, but does not require the use of a timeout. By simply stubbing the emit() method, you can test that it is called and verify its arguments. This assumes that your object inherits from Node's EventEmitter class. The name of the emit method may be different in your case.
var sinon = require('sinon');
// ...
describe("#someMethod", function(){
it("should emit `some_event`", function(done){
var myObj = new MyObj({/* some params */})
// This assumes your object inherits from Node's EventEmitter
// The name of your `emit` method may be different, eg `trigger`
var eventStub = sinon.stub(myObj, 'emit')
myObj.someMethod();
eventStub.calledWith("some_event").should.eql(true);
eventStub.restore();
done();
})
})