我如何用玩笑测试承诺延迟?

How do I test promise delays with jest?

这是我用来延迟处理(退避)的代码

export function promiseDelay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

我想测试一下,但我做不到。我尝试使用 fakeTimers,但我的测试永远不会结束。

test('promiseDelay delays for 1s', async (done) => {
    jest.useFakeTimers();
    Promise.resolve().then(() => jest.advanceTimersByTime(100));
    await promiseDelay(100);
  });

我认为你只需要 return 来自函数的 promise

test('promiseDelay delays for 1s',() => {
  jest.useFakeTimers();
  return Promise.resolve().then(() => jest.advanceTimersByTime(100));
});

然后监听setTimeout被调用一次

promiseDelay returns 在 ms 之后解析的 Promise 所以在 then 中调用 spy 并测试是否 spy 在不同的时间间隔后被调用:

describe('promiseDelay', () => {

  beforeEach(() => { jest.useFakeTimers(); });
  afterEach(() => { jest.useRealTimers(); });

  test('should not resolve until timeout has elapsed', async () => {
    const spy = jest.fn();
    promiseDelay(100).then(spy);  // <= resolve after 100ms

    jest.advanceTimersByTime(20);  // <= advance less than 100ms
    await Promise.resolve();  // let any pending callbacks in PromiseJobs run
    expect(spy).not.toHaveBeenCalled();  // SUCCESS

    jest.advanceTimersByTime(80);  // <= advance the rest of the time
    await Promise.resolve();  // let any pending callbacks in PromiseJobs run
    expect(spy).toHaveBeenCalled();  // SUCCESS
  });

});

请注意,测试代码是同步的 Timer Mocks make setTimeout synchronous but then queues a callback in PromiseJobs,因此在测试 spy 是否已被调用之前,需要允许任何排队的回调 运行。

这可以通过使用 async 测试函数并在已解决的 Promise 上调用 await 来完成,这有效地在 [=19= 结束时将其余测试排队] 在测试继续之前允许任何挂起的回调 运行。

我的回答 .

中提供了有关 promises 和虚假计时器如何交互的更多信息