'For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves

I have this test of nodejs when testing I get a error of done function not declared.

Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.

My test code is, I have the done call back but still getting the error to call the done();

    it('remove existing subdocument', (done) => {
    const Vic = new User({
      name: 'Vic',
      posts: [{ title: 'Leaning Nodejs' }]
    });

    vic.save()
      .then(() => User.findOne({ name: 'Vic' }))
      .then((user) => {
        const post = user.posts[0];
        post.remove();
        return user.save();
      })
      .then(() => User.findOne({ name: 'Vic' }))
      .then((user) => {
        assert(user.posts.length === 0);
        done();
      });
  });


Solution 1:[1]

I was facing the same issue, @MFAL's link in comment helped. I am expanding upon it.

When there is an error/incorrect assertion an error is raised inside the promise. This leads to promise rejection. Once rejected done is never called and mocha reports time out. I solved this by writing a .catch block and chaining it with the promise:

          it('resolves', (done) => {
            fooAsyncPromise(arg1, arg2).then((res, body) => {
                expect(res.statusCode).equal(incorrectValue);
                done();
            }).catch(done);
         });

Other ways as mentioned in the Wietse's blog are:

To chain a then(done, done) which handles both resolve and reject of the promise.

         it('resolves', (done) => {
           resolvingPromise.then( (result) => {
             expect(result).to.equal('promise resolved');
           }).then(done, done);
         });

Return a promise:

        it('resolves', () => {
          return resolvingPromise.then( (result) => {
            expect(result).to.equal('promise resolved');
          });
        });

Use async/wait:

        it('assertion success', async () => {
          const result = await resolvingPromise;
          expect(result).to.equal('promise resolved'); 
        });

Solution 2:[2]

I know an ugly way of doing it, just by increasing default timeout of Mocha from 2 seconds to 10 seconds this can be done by adding a flag --timeout 10000 in the test scripts i.e -

package.json

 "scripts": {
    "start": "SET NODE_ENV=dev && node server.js",
    "test": "mocha --timeout 10000"
  }

Solution 3:[3]

You can just add timeout to the specific test to increase/override the default timeout which is 2 seconds. I had the same issue but was able to by pass it using:

it('Test', (done) => { 
//your code  
done();
}).timeout(10000);

Solution 4:[4]

My problem was the timeout itself (extending it didn't help) so my solution was

it("it should test methods",function(){
     this.timeout(0);
   });

as you see you don't need the done argument

Solution 5:[5]

If none of the above helps, try to get rid of "done" and use async function() instead

it("Test Post Request", async function () {
    _code_
})

Solution 6:[6]

The idea is to increase the timeout.
Alternative way is to do that in required method only:

 it('remove existing subdocument', function(done) {
         this.timeout(10000);
      //your code is here
      done();
    });

That help me to resolve the problem.

Solution 7:[7]

In package.json file you can fix this error by using --timeout 15000,
just like I use below.

"scripts": {
  "start": "node server/server.js",
  "test": "export NODE_ENV=test || SET \"NODE_ENV=test\" && mocha --timeout 15000 server/**/*.test.js",
  "test-watch": "nodemon --exec 'npm test'"
}

This error occurs because of mocha.

Solution 8:[8]

I was also getting that error, and after several hours of researching and debugging, I found the root cause.

Consider this test:

const delay = require('delay')

describe('Test', function() {
    it('should resolve', async function(done) {
      await delay(1000)
    })
})

When I run the test, I get this error:

Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.

Now consider this slightly different test, where the done argument is removed:

const delay = require('delay')

describe('Test', function() {
    it('should resolve', async function() {
      await delay(1000)
    })
})

When I run this test, it passes.

Somehow the presence of the done argument in the async function breaks the test, even if it's not used, and even if done() is called at the end of the test.

Using Mocha version 7.2.0

Solution 9:[9]

You can also add the timeout in before or beforEach.

describe('new loading express', function () {

  before(function () {
    this.timeout(20000); // 20 second timeout for setup
  });

});

Solution 10:[10]

Happe with me when I returned back maintaining an old node-module from Node6 to Node 13. The fix is simple :

  • adding a file mocha.opts under the folder of tests.
  • The content of this file is one line : --timeout 10000

Solution 11:[11]

If you are facing this error in the VS Code extenstion development, you need to add timeout to the Mocha instance in the src/test/suite/index.ts, for example:

// Create the mocha test
const mocha = new Mocha({
    ui: 'tdd',
    color: true,
    timeout: 10000 // Your application ideal timeout here
});

Solution 12:[12]

I had the same Error Message, in my case it was caused of the usage of sinon.useFakeTimers()

That call conflicts with the setTimeout() used in my code. After removing the that all worked fine.

Solution 13:[13]

I had the same error and it is actually because I passed done and called done in then. So removing done makes the test pass. I was calling an async function in route I was testing

Solution 14:[14]

The answer by @Simon Boudrias here Why am I getting "Error: Resolution method is overspecified"? worked for me. I was missing just the await Promise.resolve() I initially thought by calling after(async () => driver && driver.quit()); would have cleaned up everything and properly existed. Off course don't forget to set .timeout(10000); to whatever amount of time you need so that you are covered incase you need more than the default 2000 to run your test.

Solution 15:[15]

You can work with

  • async-await,
  • return Promise-then,
  • function(done)-done()

In every situation there are timeout for

  • global timeout which can be given by command parameter as given below

  • timeout for funcitons (before/after[each|all], it) given as chain method or parameter

    /usr/bin/node ./node_modules/mocha/bin/_mocha -u bdd --colors /home/cemt/cli-js/test/**/*.spec.js

Test code:

describe('NSSF', function () {

    var a = 0

    beforeAll(async function () {
        console.log(">>> 1. a: ", a);
        await new Promise((resolve, reject) => {
            var intt = setInterval(() => {
                console.log(">>> a: ", ++a);
                if (a == 10) {
                    clearInterval(intt)
                    resolve();
                }
            }, 800);
        });
    }, 12000);

    it('a should be set to 1', () => {
        console.log("-----1");
        return new Promise(resolve => {
            console.log("-----2");
            setTimeout(() => {
                resolve(1)
            }, 14000)
        }).then(a => {
            expect(a === 1);
        })
    }, 3000);
})

Without timeout setting:

enter image description here

With timeout setting:

/usr/bin/node ./node_modules/mocha/bin/_mocha --slow 5000 -u bdd --timeout 10000 --colors /home/cemt/cli-js/test/**/*.spec.js

enter image description here

Launch.json in VS Code

enter image description here

Solution 16:[16]

From the official Mocha page (Mocha page)-> use the next flag when starts mocha:

--timeout , -t Update in v6.0.0: --no-timeout is implied when invoking Mocha using inspect flags. It is equivalent to --timeout 0. --timeout 99999999 is no longer needed.

Specifies the test case timeout, defaulting to two (2) seconds (2000 milliseconds). Tests taking longer than this amount of time will be marked as failed.

To override you may pass the timeout in milliseconds, or a value with the s suffix, e.g., --timeout 2s and --timeout 2000 are equivalent.

To disable timeouts, use --no-timeout.

Note: synchronous (blocking) tests are also bound by the timeout, but they will not complete until the code stops blocking. Infinite loops will still be infinite loops!

Solution 17:[17]

I had the same issue. I had a before in my code. All it took to fix it was to add this.timeout(0); as the first line in the before function, and use async-await throughout the file and removing done().

Solution 18:[18]

If tests are longer than the time you have set, you will keep getting the error, Updating package.json file, with ( adding the second test with --no-timeout attribute solved my issue.

"scripts": {

"test": "cross-env PORT=8000 mocha --watch",
"test": "cross-env PORT=8000 mocha --watch --no-timeout"*,

Solution 19:[19]

Not need to add done(). Just extend mocha timeout globaly:

Option 1: In package.json add new property:

  "mocha": {
    "timeout": "10000"
  }

Option 2: Specify configuration file and add timeout option in it

i.e. .mocharc.yml

with entry: timeout: '2000' # same as "timeout: '2s'"

see examples: https://github.com/mochajs/mocha/blob/master/example/config/.mocharc.yml