kalpa
kalpa

Reputation: 697

How to test a function that uses setTimeout() internally with mocha?

Consider the below function,

function helloAfter100ms(){
  setTimeout(function(){
    console.log('hello');
  },100)
}

Test code with mocha,

describe('#helloAfter100ms()',function(){
  it('console logs hello ONLY after 100ms',function(){
    // what should go here
  })
})

Upvotes: 7

Views: 6590

Answers (2)

Kraylog
Kraylog

Reputation: 7553

I think you're trying to test something that you shouldn't. The name of your test suggests you don't trust that the setTimeout function calls the console.log only after the given timeout.

Since this is not your code, you should probably not unit test it. Furthermore, setTimeout is probable something you can be sure works properly.

So what's left to test? Your code - the code that calls setTimeout. You can make sure that you're calling setTimeout correctly.

As to how this is done - there are two sinon features you can use. The first is useFakeTimers which gives you control of the clock. The second is a spy, which you should use on the console.log to make sure it was called.

describe('#helloAfter100ms()',function(){
  it('console logs hello ONLY after 100ms',function(){
    const clock = sinon.useFakeTimers();
    const logSpy = sinon.spy(console, 'log');
    helloAfter100ms();
    expect(logSpy).to.not.have.been.called;
    clock.tick(100);
    expect(logSpy).to.have.been.calledOnce;
    logSpy.restore();
    clock.restore();
  }
}

Upvotes: 11

Hack it
Hack it

Reputation: 403

Updated: like this:

describe('helloAfter100ms', function(){
   it('console logs hello ONLY after 100ms', function(done){
       setTimeout(function(){
           console.log('hello.');
           done();
       }, 100)
   })
})

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

Upvotes: -1

Related Questions