Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
  })
})
like image 888
kalpa Avatar asked Oct 15 '17 11:10

kalpa


1 Answers

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();
  }
}
like image 74
Kraylog Avatar answered Oct 17 '22 20:10

Kraylog