Home > Software engineering >  Cascading timers and an async function in jest
Cascading timers and an async function in jest

Time:12-15

In this test code,

test('test', async () => {
  jest.useFakeTimers();

  const cb = jest.fn();
  const func = jest.fn().mockResolvedValueOnce(1);

  setTimeout(async () => {
    setTimeout(() => {
      cb();
    }, 1000);
  }, 1000);

  jest.runAllTimers();
});

since jest.runAllTimers() simulates enough passing time so that cb() is hit. But in this one,

test('test', async () => {
  jest.useFakeTimers();

  const cb = jest.fn();
  const func = jest.fn().mockResolvedValueOnce(1);

  setTimeout(async () => {
    await func();
    setTimeout(() => {
      cb();
    }, 1000);
  }, 1000);

  jest.runAllTimers();

  expect(cb).toHaveBeenCalledTimes(1);
});

cb() is never hit.

How should I modify this test this code, so that it properly hits cb and the test passes?

CodePudding user response:

Your timer is defined after the promise (returned from func) is resolved. So in order to run that timer you have to await for it to be initiated. You can do that by awaiting on the promise returned by func.

To access the data retuned by a jest mock function you can use it's .mock property

e.g.

test('test', async () => {
    jest.useFakeTimers();
  
    const cb = jest.fn();
    const func = jest.fn().mockResolvedValueOnce(1);
  
    setTimeout(async () => {
      await func();
      setTimeout(() => {
        cb();
      }, 1000);
    }, 1000);
  
    jest.runAllTimers();
    await func.mock.results[0].value
    jest.runAllTimers();
  
    expect(cb).toHaveBeenCalledTimes(1);
  });
  • Related