Search code examples
javascriptnode.jspromisesettimeoutsinon

setTimeout not triggered while using Sinon's fake timers


I have a test similar to what is shown below. Basically I want to test if a specific method is getting delayed.

The following example works as expected, i.e. the resolve method gets called and the test passes:

it(`should delay execution by 1 second`, function () {
  const clock = sandbox.useFakeTimers();

  const p = new Promise(function (resolve) {
    setTimeout(resolve, 1000);
  });

  clock.tick(1000);

  return p;
});

However, if I wrap the setTimeout in another Promise, the resolve never gets called:

it(`should delay execution by 1 second`, function () {
  const clock = sandbox.useFakeTimers();

  const p = Promise.resolve()
    .then(() => {
      return new Promise(function (resolve) {
        setTimeout(resolve, 1000); // resolve never gets called
      });
    });

    clock.tick(1000);

    return p;
  });

What's the problem here?

I'm using Sinon 2.1.0 and native promises on Node 6.9.5.


Solution

  • The problem appears to be that you are ticking the clock before the timeout is started - which happens asynchronously, in a promise callback, in your second snippet.

    This should work:

    it(`should delay execution by 1 second`, function () {
      const clock = sandbox.useFakeTimers();
    
      return Promise.resolve().then(() => {
        return new Promise(function (resolve) {
          setTimeout(resolve, 1000);
          clock.tick(1000); // resolve gets called now
        });
      });
    });