Search code examples
javascriptnode.jssinon

Sinon clock.tick doesn't advance time for setTimeout


I am writing a test for an async function which performs a series of tasks and at one point waits for 60 seconds before doing some more tasks. I am trying to use sinon.useFakeTimers() to skip those 60 seconds so that I can test the logic after the delay.

foo.js

module.exports.foo = async f => {
  // ... more code ...
  await new Promise((resolve, reject) => {
    setTimeout(resolve, 60000);
  });
  // ... more code ...
  f();
  // ... more code ...
};

test-foo.js

const sinon = require('sinon');
const expect = require('chai').expect;

const { foo } = require('./foo');

describe('Module Foo ', function() {
  it('call function after 1 minute', function() {
    var clock = sinon.useFakeTimers();
    const bar = sinon.stub();

    foo(bar);
    expect(bar.called).to.be.false;
    clock.tick(100000);
    expect(bar.called).to.be.true; // this one fails
  });
});

I tried putting sinon.useFakeTimers(); in various other places, but the Promise doesn't resolve and the stub I pass into foo doesn't get called.


Solution

  • Make your test function async and await a resolved Promise after advancing your clock to give the Promise callback queued by the await in foo a chance to run before doing your assertion:

    const sinon = require('sinon');
    const expect = require('chai').expect;
    
    const { foo } = require('./foo');
    
    describe('Module Foo ', function() {
      it('call function after 1 minute', async function() {  // <= async test function
        var clock = sinon.useFakeTimers();
        const bar = sinon.stub();
    
        foo(bar);
        expect(bar.called).to.be.false;  // Success!
        clock.tick(100000);
        await Promise.resolve();  // <= give queued Promise callbacks a chance to run
        expect(bar.called).to.be.true;  // Success!
      });
    });
    

    For complete details see my answer here which uses Jest and Jest timer mocks but the concepts are the same and also apply to Mocha and Sinon fake timers.