463

I'm submitting a network request in a test case, but this sometimes takes longer than 2 seconds (the default timeout).

How do I increase the timeout for a single test case?

ted
  • 13,596
  • 9
  • 65
  • 107
Mahendra S
  • 4,659
  • 2
  • 13
  • 4

8 Answers8

736

Here you go: http://mochajs.org/#test-level

it('accesses the network', function(done){
  this.timeout(500);
  [Put network code here, with done() in the callback]
})

For arrow function use as follows:

it('accesses the network', (done) => {
  [Put network code here, with done() in the callback]
}).timeout(500);
extempl
  • 2,987
  • 1
  • 26
  • 38
Dan Kohn
  • 33,811
  • 9
  • 84
  • 100
  • 25
    timeout is in milliseconds, and it defaults 2000. – Ethan Mick Oct 26 '14 at 04:10
  • 56
    I was using es6 arrow functions and had to fall back to old 'function' definitions for "this" to work. – Aruna Herath Nov 13 '15 at 05:24
  • Do you have a simple example of this "[Put network code here, with done() in the callback]"? This part confuses me. – ayjay Nov 25 '15 at 18:05
  • 1
    Also works for hooks, like `before(function(done){this.timeout(5 * 1000);...});` – jpsecher Mar 09 '16 at 11:44
  • 2
    @AH The reason the arrow function didn't work is because of [lexical this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#Lexical_this) – rtf Apr 12 '16 at 22:40
  • 16
    is there a way to get it to work with arrow function? edit: add `.timeout(500)` to end of `it(...).timeout(500)` – chovy Jan 18 '17 at 07:11
  • 3
    Mocha specifically discourages arrow functions: https://mochajs.org/#arrow-functions. IMO it's worth pointing out in the answer. – neverendingqs Nov 13 '17 at 18:45
  • doesn't work for me, getting a "'this' implicitly has type 'any' because it does not have a type annotation.ts(2683)" (no, I'm not using arrow functions) – Ronin Dec 18 '18 at 00:08
158

If you wish to use es6 arrow functions you can add a .timeout(ms) to the end of your it definition:

it('should not timeout', (done) => {
    doLongThing().then(() => {
        done();
    });
}).timeout(5000);

At least this works in Typescript.

Nisse Engström
  • 4,738
  • 23
  • 27
  • 42
Chris Sparrow
  • 1,589
  • 1
  • 9
  • 3
  • 3
    This works, but `.timeout` is not included in the DefinitelyTyped typings for mocha: http://i.imgur.com/jQbWCn1.png - Using `this.timeout(2000)` or `this.slow(500)` with a regular old function works and compiles without errors – Leon Adler May 02 '16 at 21:32
  • 3
    Sadly, this only works for `it`, it doesn't work for `describe`. – robrich May 13 '16 at 19:44
  • 3
    is there a way to do this for `describe()` or `context()`? – chovy Jan 26 '17 at 06:43
  • 1
    @LeonAdler `.timeout` is now included in DefinitelyTyped's Mocha typings at: `Mocha.IRunnable`. However, if you're using the Webstorm IDE for running these tests, a note of caution: for whatever reason, WebStorm's Mocha integration plugin still does not recognise Mocha tests with `.timeout()` appended (meaning that no 'run' button appears next to them), and thus I advocate avoiding arrow functions to allow use of `this.timeout()` instead. – Jamie Birch Aug 02 '17 at 11:30
  • This is perfect. For async function returning a promise you can leave out done(). – billoverton Feb 19 '20 at 17:41
  • This also doesn't work for `it.only()`. You have to `describe.only()` if you want to use `.timeout()` with `it` – apoteet Jun 22 '23 at 21:22
77

(since I ran into this today)

Be careful when using ES2015 fat arrow syntax:

This will fail :

it('accesses the network', done => {

  this.timeout(500); // will not work

  // *this* binding refers to parent function scope in fat arrow functions!
  // i.e. the *this* object of the describe function

  done();
});

EDIT: Why it fails:

As @atoth mentions in the comments, fat arrow functions do not have their own this binding. Therefore, it's not possible for the it function to bind to this of the callback and provide a timeout function.

Bottom line: Don't use arrow functions for functions that need an increased timeout.

chriskelly
  • 7,526
  • 3
  • 32
  • 50
  • 2
    Because arrow functions does not have this at all. Read more here: https://blog.getify.com/arrow-this/ – atoth Apr 29 '16 at 11:54
  • 2
    Yes but I have explained this in the answer. See my comment. // inside the code. I should probably explain it outside the code block to make it clearer. this does exist but it comes from the outer scope. – chriskelly Apr 29 '16 at 11:59
  • 1
    My explanation is more accurate. There is no `this` binding on arrow functions - not the same way would suggest they have some kind of, just different. They only have lexical scopes. You can't bind non-existing this. That's why `.bind`, `.call`, etc. does not work with it. – atoth Apr 29 '16 at 12:01
  • 1
    That's true - and your right it's more accurate. Thanks – chriskelly Apr 29 '16 at 12:07
  • 2
    I'd say that this is why you should only use fat arrows when you need them, but I've lost track of what `this` is. – xdumaine Sep 26 '16 at 19:12
  • _Bottom line:_ Don't use `this`. – Dem Pilafian Aug 30 '18 at 03:47
58

If you are using in NodeJS then you can set timeout in package.json

"test": "mocha --timeout 10000"

then you can run using npm like:

npm test
  • 2
    That's for all test cases, not a single test case – garryp Apr 03 '19 at 08:41
  • 1
    Agreed that this doesn't answer the question, but it was sufficient for my use case where I didn't care if it increased for all tests. I think a lot of people who end up here may not care if it's for one test or all, so I appreciate this answer being here. – billoverton Jan 08 '20 at 23:01
25

From command line:

mocha -t 100000 test.js
andrey
  • 1,867
  • 3
  • 21
  • 34
  • 18
    This increases the timeout *for all test cases* rather than "for a particular test case" like the question asks. – Louis Feb 15 '16 at 00:18
17

You might also think about taking a different approach, and replacing the call to the network resource with a stub or mock object. Using Sinon, you can decouple the app from the network service, focusing your development efforts.

David Souther
  • 8,125
  • 2
  • 36
  • 53
  • 7
    It's not *entirely* irrelevant; frequently, it makes sense to stub the network response so you're not reliant on that machine being up or returning the correct response. If you're testing the response itself, however, then yeah, you still need to do it. – aendra Nov 17 '15 at 14:41
  • 2
    I'm using sinon/mocha to build some integration tests, so higher timeouts are relevant. – jcollum Jan 17 '17 at 19:19
15

For test navigation on Express:

const request = require('supertest');
const server = require('../bin/www');

describe('navigation', () => {
    it('login page', function(done) {
        this.timeout(4000);
        const timeOut = setTimeout(done, 3500);

        request(server)
            .get('/login')
            .expect(200)
            .then(res => {
                res.text.should.include('Login');
                clearTimeout(timeOut);
                done();
            })
            .catch(err => {
                console.log(this.test.fullTitle(), err);
                clearTimeout(timeOut);
                done(err);
            });
    });
});

In the example the test time is 4000 (4s).

Note: setTimeout(done, 3500) is minor for than done is called within the time of the test but clearTimeout(timeOut) it avoid than used all these time.

Allain Lalonde
  • 91,574
  • 70
  • 187
  • 238
alditis
  • 4,633
  • 3
  • 49
  • 76
13

This worked for me! Couldn't find anything to make it work with before()

describe("When in a long running test", () => {
  it("Should not time out with 2000ms", async () => {
    let service = new SomeService();
    let result = await service.callToLongRunningProcess();
    expect(result).to.be.true;
  }).timeout(10000); // Custom Timeout 
});
Pang
  • 9,564
  • 146
  • 81
  • 122
Otpidus
  • 489
  • 5
  • 5