Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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?

In the first piece of code done() refers to the done parameter. In the second piece of code done() refers to definition of done() found in the current scope. – Ely Jun 5, 2016 at 21:32 The testing framework needs to know when the asynchronous operation is finished so it can check that the test passed. So it gives you a done() function that you call to let it know. – Josiah Keller Jun 5, 2016 at 21:34

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 called done due to tradition. You could call it complete, cb or platypus and it would work just the same.) If you call done without a value, the test is successful. With a value, the test is a failure and the value should be an Error object or an object derived from Error.

  • 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 to done it should be an Error or derived from Error). The done in there is another done function which is private to Mocha.

    @Luis thank you for this detailed answer! do have an article that explains the whole concept of done() function in the javascript ecosystem, please? – Thamer Jan 6, 2020 at 22:45

    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.

    All test cases including before(), after(), beforeEach(), afterEach() must call done() at the end to tell Mocha that all tasks are completed.

    If done() is missing, a timeout exception will be raised because Mocha will wait for done() until timeout.

    But why? Sometimes "done" is not included in the function parameter and the test just ends. – ThePumpkinMaster Jun 6, 2016 at 3:46 can i see your sample code? from my experiences, before(), after(), beforeEach(), afterEach(), it() must have done() at the end – Alongkorn Jun 6, 2016 at 3:47 the callbacks before, after and so on are just like "normal" mocha tests. they can either have a done callback or not. if present in the functions argument list, mocha will timeout if done() is not called, otherwise it just ends after the last function call. One exception is, if your test returns a promise - then mocha will resolve that promise... – codewandler Jan 31, 2017 at 8:46

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.