18

I'm writing a test in Mocha / Node js and want to use a setTimeout to wait for a period before executing a block of code.

How can I accomplish this?

It appears that within a Mocha test case, setTimeout() does not work. (I am aware that you can setTimeout per test case and per test file, that's not what I need here.)

In a js file run with Node, ie, node miniTest.js, this will wait 3 seconds, then print the line inside the setTimeout function.

miniTest.js

console.log('waiting 3 seconds...');
setTimeout(function() {
    console.log('waiting over.');
}, 3000);

In a js file run with Mocha, ie, mocha smallTest.js, this will not wait, and will finish executing and exit without ever printing the line inside the setTimeout function.

smallTest.js:

mocha = require('mocha');

describe('small test', function() {
    it('tiny test case', function() {
        console.log('waiting 3 seconds...');
        setTimeout(function () {
            console.log('waiting over.')
        }, 3000);
    });
});
nyarasha
  • 1,119
  • 1
  • 14
  • 24

4 Answers4

31

You are forgetting to pass parameter in it('tiny test case', function() and call done() after console.log in setTimeout method.

describe('small test', function(){
   it('tiny test case', function(done){
       console.log('waiting 3 seconds');
       setTimeout(function(){
           console.log('waiting over.');
           done();
       }, 3000)
   })
})
Neelabh Singh
  • 2,600
  • 12
  • 51
  • 88
  • Thank you so much! This runs and indeed, waits the allotted time. – nyarasha Sep 23 '15 at 14:09
  • Hi - why does the `done` need to be added? If there was simply a test with many steps, it it ok just to use `this.timeout = 60000` ? – userMod2 Aug 17 '17 at 02:45
  • 3
    @userMod2 Yes, as long as your code is synchronous, running each step one after the other, setting a timeout is sufficient. But the code in the OP (any code using `setTimeout`) is *asynchronous*, meaning that it returns immediately and the function argument gets run at a future time. It's understandably confusing that there are two kinds of things both called "timeouts" here: `this.timeout = x` means "if my test runs longer than x ms, consider it a failure". `setTimeout(function, x)` means "after waiting x ms, run my function". – frankleonrose Oct 09 '17 at 20:23
  • 2
    How to do this in new async await syntax? – Ferit Aug 15 '18 at 10:54
2

You need to have done passed as a parameter in your test which will be invoked once the test passes.

You can write your test like

mocha = require('mocha');

describe('small test', function(done) {
    it('tiny test case', function() {
       console.log('waiting 3 seconds...');
       setTimeout(function () {
           console.log('waiting over.');
           done();
       }, 3000);
    });

});

This will wait 3 seconds after that it will print 'waiting over' and pass the test. You can also have a condition inside the timeout depending upon whether the condition is satisfied or not you can pass the test by calling

done();

or fail the test by either throwing an error or passing the error message in

done("Test Failed");
Vipul
  • 566
  • 5
  • 29
1

Have your test function take a parameter (typically called done). Mocha will pass a function that you'll call in the setTimeout function (e.g. after console.log call done()).

See https://mochajs.org/#asynchronous-code.

JMM
  • 26,019
  • 3
  • 50
  • 55
1

This is a complete example. You need to call done() in every assertion you make. You can leave out the before function and do the setTimeout in one of your it functions, but it should still use and call done() after assert.

var foo = 1;
before(function(done) {
  setTimeout(function(){
    foo = 2;
    done();
  }, 500)
});

describe("Async setup", function(done){

  it("should have foo equal to 2.", function(done){
    expect(foo).to.be.equal(2);
    done();
  });

  it("should have foo not equal 3.", function(done){
    expect(foo).to.be.not.equal(3);
    done();
  });

});
Ska
  • 6,658
  • 14
  • 53
  • 74