3

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.

Hugo Durães
  • 55
  • 1
  • 2
  • 7

1 Answers1

12

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
    });
  });
});
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Had to make a few changes but this led me to the right path! Thanks :) – Hugo Durães Mar 27 '17 at 16:45
  • how would you do if you could not change the inner promise? I can not put the clock.tick here, but the promise is waiting for the setTimeout to resolve. – Félix Brunet Dec 22 '17 at 16:09
  • @FélixBrunet You need to put the click tick somewhere after the `setTimeout` call. It would work after the `new Promise` as well. – Bergi Dec 22 '17 at 16:26