In Mochajs, they use "done()" to test for asynchronous code, like so:
describe('User', function() {
describe('#save()', function() {
it('should save without error', function(done) {
var user = new User('Luna');
user.save(function(err) {
if (err) throw err;
done();
});
});
});
});
What does this mean exactly? I did console.log(done.toString()) and I got this:
function (err) {
if (err instanceof Error || toString.call(err) === '[object Error]') {
return done(err);
}
if (err) {
if (Object.prototype.toString.call(err) === '[object Object]') {
return done(new Error('done() invoked with non-Error: '
+ JSON.stringify(err)));
}
return done(new Error('done() invoked with non-Error: ' + err));
}
done();
}
Is the done() at the very end here different than the done() in the first piece of code?
All test case including before(), after(), beforeEach(), afterEach() must call done() at the end to tell mocha that all tasks are completed.
If done() is missing, timeout exception will occurs because mocha will wait for 'done()' until timeout.
Because of asynchronous nature of node.js, you have to tell to Mocha that your finished test.
For classic synchronous languages, you are done when the method has finished. But in node, first the whole method is executed and then, some time after is executed inner body of
user.save()
.The Mocha just waits with test until
done()
, is called, because it does not have any other option to find if something else should be executed or it is finished.The output you have is just body of function
done
.Mocha is able to handle synchronous and asynchronous tests. When you run a synchronous test, you can just pass it as an anonymous function to
it
and you don't have to do anything else: Mocha knows the test is over when the function returns. However, if you are running an asynchronous test, you have to tell Mocha that the test is asynchronous. There are two ways to do this:Declare that the anonymous function you pass to
it
takes a parameter. Mocha will call your anonymous function with a single parameter which is a function you must call to indicate that your test is over. (This parameter is calleddone
due to tradition. You could call itcomplete
,cb
orplatypus
and it would work just the same.) If you calldone
without a value, the test is successful. With a value, the test is a failure and the value should be anError
object or an object derived fromError
.Return a promise: Mocha will wait for the promise to be resolved or rejected. If resolved, the test is successful. If rejected, the test failed.
The code you see when you do
done.toString()
is just the code of the function that Mocha passes to your test when you declare it to take a parameter. You can see in it some of what I mentioned above (e.g. if you pass a parameter todone
it should be anError
or derived fromError
). Thedone
in there is anotherdone
function which is private to Mocha.