How to avoid timeouts in mocha testcases?
Asked Answered
C

5

11

Here I am attaching my code, I am passing done callback and using supertest for request. Since I am using assert/expect in my testcase inside request.end block why I need to worry about timeout? What is mistake I am making here.

it('should get battle results ', function(done) {
    request(url)
      .post('/compare?vf_id='+vf_id)
      .set('access_token',access_token)
      .send(battleInstance)
      .end(function(err, res){  // why need timeout
        if (err) return done(err);
        console.log(JSON.stringify(res.body));
        expect(res.body.status).to.deep.equal('SUCCESS');
        done();
      });
 });

Testcase results following response: Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

If I am running my testcases with mocha command then its show this error while If I am running test mocha --timeout 15000 then testcase is passing correctly. But I want to avoid timeout, How can I do that?

Coralline answered 28/4, 2016 at 6:54 Comment(1)
Possible duplicate of Change default timeout for mochaTanh
T
13

If I am running my testcases with mocha command then its show this error while If I am running test mocha --timeout 15000 then testcase is passing correctly. But I want to avoid timeout, How can I do that?

You can't avoid timeouts, since it looks like you're testing a remote service. If, for whatever reason, the request to that service takes a long time, you will run into timeouts.

You can tell Mocha to disable for timeout checking by setting the timeout to 0, but that's probably also not ideal because it may cause each test case to take an excessive amount of time.

As an alternative, you can mock request (which I assume is superagent) so you can control the entire HTTP request/response flow, but since it looks like you're testing a remote service (one which you have no control over) that would make this particular test case moot.

Taxable answered 28/4, 2016 at 8:24 Comment(6)
Okay but if I can't avoid timeouts then how I will know how much timeout I should keep, I can't do hit and trial everytime I write a testcase and also it depends on network speed I guess ?. So any generic approach to test these services?Coralline
The only thing you can do is set an upper limit to the timeout (like 5 minutes), or disable them altogether. But since you're basically testing an external service, there isn't a generic solution to avoid timeouts.Taxable
One more doubt I have is that since we are using assertion like expect (and also passing done callback) in request.end(), so that means done callback should be passed after getting response. isn't it? I am referring to following part of code. .end(function(err, res){ // why need timeout if (err) return done(err); console.log(JSON.stringify(res.body)); expect(res.body.status).to.deep.equal('SUCCESS'); done(); });Coralline
@AnupamJakhar yes, you need to wait for the .end() callback to get called before you can verify the response and end the test case by calling done().Taxable
Thanks for your replies, But I am asking that why to give timeout as I am already waiting for .end() and also I am calling done() already inside .end() callback.Coralline
.end() is part of superagent, not Mocha. They are independent of each other: the timeout handling of Mocha is not aware of how you're using superagent, and that it may take some time to complete the request.Taxable
G
9

In mocha a default timeout of 2 seconds (2000ms) is set by default.

You can extend the default (global) timeout from the command line using the --timeout xxxx flag.

If you want instead to change the timeout for a specific test case you can use the this.timeout( xxxx ) function - note it does not work for arrow functions - (where xxxx is a number like 20000 representing milliseconds).

it('My test', function(){
  this.timeout(5000);
  //... rest of your code
});

You can also set a timeout of a set of test cases (wrapped by a describe):

describe("My suite", function(){
  // this will apply for both "it" tests
  this.timeout(5000);

  it( "Test 1", function(){
     ...
  });

  it( "Test 2", function(){
     ...
  });

});

It also works for before, beforeEach, after, afterEach blocks.

More documentation is available here: https://mochajs.org/#timeouts

Consider that 2 seconds is usually a good amount of time to run your tests so I would say that extend the default timeout should be an exception, not the common rule in your tests. Also if your test is not async and you have to extend the timeout I would strongly suggest to review the function that is taking so long before extending the timeout.

Gull answered 28/4, 2016 at 8:22 Comment(1)
Great answer and wise advice - "so I would say that extend the default timeout should be an exception, not the common rule in your tests". Disappointing that answered over a year ago and no up voting. Does any really test their stuff in anger or are we all still kicking the tyres?Psia
H
2

Mocha : Timeouts

Test-specific timeouts may also be applied, or the use of this.timeout(0) to disable timeouts all together:

To disable the timeout from happening simply set it to 0. I use mocha <file> --timeout 0 when I'm debugging so the timeout error does not get thrown.

Hydrant answered 29/11, 2020 at 23:1 Comment(0)
E
0

Here is what you need

mocha timeouts

describe('a suite of tests', function() {
  this.timeout(500);

  it('should take less than 500ms', function(done){
    setTimeout(done, 300);
  });

  it('should take less than 500ms as well', function(done){
    setTimeout(done, 250);
  });
})
Emulsoid answered 28/4, 2016 at 7:5 Comment(0)
E
0

You can try adding "--no-timeouts" in your mocha script, like this:

mocha --no-timeouts

Eclosion answered 7/7, 2023 at 19:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.