52

I want to set timeout value on before hook in mocha test cases. I know I can do that by adding -t 10000 on the command line of mocha but this will change every test cases timeout value. I want to find a way to change the timeout programmatically below is my code:

describe('test  ', () => {

  before((done) => {
        this.timeout(10000);
         ...

it will complain about the line this.timeout(1000) that timeout is not defined. How to set the timeout on before hook.

Joey Yi Zhao
  • 37,514
  • 71
  • 268
  • 523

4 Answers4

76

You need to set a timeout in your describe block rather than in the hook if you want it to affect all the tests in the describe. However, you need to use a "regular" function as the callback to describe rather than an arrow function:

describe('test', function () {
  this.timeout(10000);

  before(...);

  it(...);
});

In all places where you want to use this in a callback you pass to Mocha you cannot use an arrow function. You must use a "regular" function which has its own this value that can be set by Mocha. If you use an arrow function, the value of this won't be what Mocha wants it to be and your code will fail.

You could set a different timeout for your before hook but there are two things to consider:

  1. Here too you'd need to use a "regular" function rather than an arrow function so:
before(function (done) { 
  this.timeout(10000);
  1. This would set a timeout only for the before hook and would not affect your tests.
felixleo22
  • 65
  • 9
Louis
  • 146,715
  • 28
  • 274
  • 320
  • 1
    Note that setting the timeout in before, e.g. `before(done => {this.timeout(10000); setTimeout(()=>{done()}, 2500)});`, does **not** work. You must set the timeout before `before`. – ericP Jun 05 '18 at 12:42
  • 1
    @ericP The example you show does not change the timeout *of the before hook* because you are using an arrow function. So `this.timeout()` executes on the *wrong `this`*. If you change the function you pass to `before` to a regular function, then `this.timeout()` will operate on the correct `this` and the timeout will apply to your `before` hook. That was the first "thing to consider" I listed at the end of my answer. – Louis Jun 05 '18 at 13:29
  • The arrow function is explicitly so i *can* access the this of the describe function. Give it a try with and without arrow functions. – ericP Jun 11 '18 at 14:17
  • 2
    @ericP I did try it before I responded the first time. What I wrote is correct: if you just change your arrow function to a regular function in the code you show, the code *will* work. You decided to use code which my answer says you should not use, and then it does not work. Well... – Louis Jun 11 '18 at 14:33
  • @Louis thanks for the note -- forgot you can't do arrow functions with "this" keywords – howard Sep 28 '22 at 05:23
11

as instructed at https://mochajs.org/#hook-level, you have to use a regular function call to set the timeout.

before(function(done) {
  this.timeout(3000); // A very long environment setup.
  setTimeout(done, 2500);
});

if you insist on use arrow or async function in the hook. You may do it this way:

before(function (done) {
  this.timeout(3000);
  (async () => {
    await initilizeWithPromise();
  })().then(done);
});

It is quite helpful and nice-looking if you got multiple async calls to be resolved in the hook.

updated: fuction def works well with async too. So this hook can be upgraded to

before(async function () {
  this.timeout(3000);
  await initilizeWithPromise();      
});

So it provides benefits from both this and await.

By the way, mocha works pretty fine with promises nowadays. If timeout is not a concern. Just do this:

before(async () => {
  await initilizeWithPromise();
});
felixleo22
  • 65
  • 9
aGuegu
  • 1,813
  • 1
  • 21
  • 22
9

You can also call timeout() on the return value from describe, like this:

describe('test', () => {
  before(...);
  it(...);
}).timeout(10000);

With this approach you can use arrow functions, because you're no longer relying on this.

felixleo22
  • 65
  • 9
curran
  • 1,261
  • 13
  • 8
1

Calling this.timeout(milliseconds); in the before hook is correct. Anyway, you need to use a regular function for the hook (function (done) ...) rather than an arrow function (done => ...).

before(
    function(done) {
        this.timeout(10000);
        ...
    }
);

And the reason is that arrow functions have no this binding.

GOTO 0
  • 42,323
  • 22
  • 125
  • 158