Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

People also ask

How do I increase my mocha timeout?

Whenever you run Mocha at the command line, it will read this file and set a timeout of 5 seconds by default. Another way which may be better depending on your situation is to set it like this in a top level describe call in your test file: describe("something", function () { this. timeout(5000); // tests... });

How do I stop mocha testing?

As of the mocha documentation, you can add --exit flag when you are executing the tests. It will stop the execution whenever all the tests have been executed successfully or not.


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.


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.


If you are using arrow functions:

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

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:

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

Run your tests using the command test


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)