Тест Jest: setTimeout не запускается в асинхронном тесте

Я пытаюсь понять, как работает асинхронное тестирование в Jest.

То, что я пытаюсь сделать, похоже на пример из документации Jest. Это отлично работает..

function doAsync(c) {
  c(true)
}

test('doAsync calls both callbacks', () => {

  expect.assertions(2);

  function callback1(data) {
    expect(data).toBeTruthy();
  }

  function callback2(data) {
    expect(data).toBeTruthy();
  }

  doAsync(callback1);
  doAsync(callback2);
});

Но я хочу отложить вызовы обратного вызова, поэтому я попробовал это....

 function doAsync(c) {
    setTimeout(() => {
      console.log('timeout fired')
      c(true)
    }, 1000)
  }

но тест не проходит с сообщением Expected two assertions to be called but received zero assertion calls.,

Сообщение журнала "Тайм-аут сработал" не отображается в консоли.

Пожалуйста, кто-нибудь может объяснить, почему это не удается?

3 ответа

Решение

Вы должны использовать шутки таймера шутки https://jestjs.io/docs/en/timer-mocks

Сначала вы указываете jest использовать фиктивные таймеры, затем запускаете таймеры в своем тесте.

Это будет выглядеть примерно так:

function doAsync(c) {
  setTimeout(() => {
      c(true)
    }, 1000)
}

jest.useFakeTimers()

test('doAsync calls both callbacks', () => {

  expect.assertions(2);

  function callback1(data) {
    expect(data).toBeTruthy();
  }

  function callback2(data) {
    expect(data).toBeTruthy();
  }

  doAsync(callback1);
  doAsync(callback2);

  jest.runAllTimers(); // or jest.advanceTimersByTime(1000)
});

Use of jest.runAllTimers(); can lead to below error:

Ran 100000 timers, and there are still more! Assuming we've hit aninfinite recursion and bailing out...

After going through the JEST timer mocks documentation, it occurred to me that the setTimeout goes into infinite recursion as mentioned in the docs. It is recommended to use jest.runOnlyPendingTimers() and this solves the infinite recursion error.

Fast forward and exhaust only currently pending timers(but not any new timers that get created during that process)

jest.runOnlyPendingTimers();

Используйте приведенный ниже код для setTime out в своем тестовом примере.

      it('saveSubscription', () => {
  function doAsync(c) {
    setTimeout(() => {
      component.addSubscription();
      expect(component.subscription.freq).toEqual('immediate');
      component.saveSubscription();
      expect(component.subscription.name).toBe('Untitled 1');
    }, 30000);
  }
});
Другие вопросы по тегам