In mocha testing while calling asynchronous function how to avoid the timeout Error: timeout of 2000ms exceeded

node.jsmocha.jsChai

node.js Problem Overview


In my node application I'm using mocha to test my code. While calling many asynchronous functions using mocha, I'm getting timeout error (Error: timeout of 2000ms exceeded.). How can I resolve this?

var module = require('../lib/myModule');
var should = require('chai').should();

describe('Testing Module', function() {

    it('Save Data', function(done) {

        this.timeout(15000);

        var data = {
            a: 'aa',
            b: 'bb'
        };

        module.save(data, function(err, res) {
            should.not.exist(err);
            done();
        });

    });


    it('Get Data By Id', function(done) {

        var id = "28ca9";

        module.get(id, function(err, res) {

            console.log(res);
            should.not.exist(err);
            done();
        });

    });

});

node.js Solutions


Solution 1 - node.js

You can either set the timeout when running your test:

mocha --timeout 15000

Or you can set the timeout for each suite or each test programmatically:

describe('...', function(){
  this.timeout(15000);

  it('...', function(done){
    this.timeout(15000);
    setTimeout(done, 15000);
  });
});

For more info see the docs.

Solution 2 - node.js

I find that the "solution" of just increasing the timeouts obscures what's really going on here, which is either

  1. Your code and/or network calls are way too slow (should be sub 100 ms for a good user experience)
  2. The assertions (tests) are failing and something is swallowing the errors before Mocha is able to act on them.

You usually encounter #2 when Mocha doesn't receive assertion errors from a callback. This is caused by some other code swallowing the exception further up the stack. The right way of dealing with this is to fix the code and not swallow the error.

When external code swallows your errors

In case it's a library function that you are unable to modify, you need to catch the assertion error and pass it onto Mocha yourself. You do this by wrapping your assertion callback in a try/catch block and pass any exceptions to the done handler.

it('should not fail', function (done) { // Pass reference here!

  i_swallow_errors(function (err, result) {
    try { // boilerplate to be able to get the assert failures
      assert.ok(true);
      assert.equal(result, 'bar');
      done();
    } catch (error) {
      done(error);
    }
  });
});

This boilerplate can of course be extracted into some utility function to make the test a little more pleasing to the eye:

it('should not fail', function (done) { // Pass reference here!
    i_swallow_errors(handleError(done, function (err, result) {
        assert.equal(result, 'bar');
    }));
});

// reusable boilerplate to be able to get the assert failures
function handleError(done, fn) {
    try { 
        fn();
        done();
    } catch (error) {
        done(error);
    }
}

Speeding up network tests

Other than that I suggest you pick up the advice on starting to use test stubs for network calls to make tests pass without having to rely on a functioning network. Using Mocha, Chai and Sinon the tests might look something like this

describe('api tests normally involving network calls', function() {

    beforeEach: function () {
        this.xhr = sinon.useFakeXMLHttpRequest();
        var requests = this.requests = [];

        this.xhr.onCreate = function (xhr) {
            requests.push(xhr);
        };
    },

    afterEach: function () {
        this.xhr.restore();
    }


    it("should fetch comments from server", function () {
        var callback = sinon.spy();
        myLib.getCommentsFor("/some/article", callback);
        assertEquals(1, this.requests.length);

        this.requests[0].respond(200, { "Content-Type": "application/json" },
                                 '[{ "id": 12, "comment": "Hey there" }]');
        expect(callback.calledWith([{ id: 12, comment: "Hey there" }])).to.be.true;
    });

});

See Sinon's nise docs for more info.

Solution 3 - node.js

If you are using arrow functions:

it('should do something', async () => {
  // do your testing
}).timeout(15000)

Solution 4 - node.js

A little late but someone can use this in future...You can increase your test timeout by updating scripts in your package.json with the following:

     "test": "test --timeout 10000" //Adjust to a value you need
  }```

Run your tests using the command `test`

Solution 5 - node.js

For me the problem was actually the describe function, which when provided an arrow function, causes mocha to miss the timeout, and behave not consistently. (Using ES6)

since no promise was rejected I was getting this error all the time for different tests that were failing inside the describe block

so this how it looks when not working properly:

describe('test', () => { 
 assert(...)
})

and this works using the anonymous function

describe('test', function() { 
 assert(...)
})

Hope it helps someone, my configuration for the above: (nodejs: 8.4.0, npm: 5.3.0, mocha: 3.3.0)

Solution 6 - node.js

My issue was not sending the response back, so it was hanging. If you are using express make sure that res.send(data), res.json(data) or whatever the api method you wanna use is executed for the route you are testing.

Solution 7 - node.js

Make sure to resolve/reject the promises used in the test cases, be it spies or stubs make sure they resolve/reject.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsachinView Question on Stackoverflow
Solution 1 - node.jsAndreas HultgrenView Answer on Stackoverflow
Solution 2 - node.jsoligofrenView Answer on Stackoverflow
Solution 3 - node.jslukas_oView Answer on Stackoverflow
Solution 4 - node.jsDaniel MbeyahView Answer on Stackoverflow
Solution 5 - node.jssyberkittenView Answer on Stackoverflow
Solution 6 - node.jsil0v3d0gView Answer on Stackoverflow
Solution 7 - node.jskavigunView Answer on Stackoverflow