Выбор ответа Middle Тестирование обновлено

Тест debounce без ожидания

Вопрос

Как протестировать функцию с debounce 300 мс, не ожидая реальные 300 мс?

it('вызывает поиск один раз', () => {
  const search = vi.fn();
  const debounced = debounce(search, 300);
  debounced('a'); debounced('ab'); debounced('abc');
  // ???
  expect(search).toHaveBeenCalledTimes(1);
  expect(search).toHaveBeenCalledWith('abc');
});

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: vi.useFakeTimers() в начале и vi.advanceTimersByTime(300). Фейковые таймеры подменяют setTimeout, и advanceTimersByTime мгновенно прокручивает виртуальное время, выполняя созревшие таймеры.

Варианты ответа

  1. vi.useFakeTimers() в начале и vi.advanceTimersByTime(300)правильный ответ
  2. Вместо ??? написать await new Promise(r => setTimeout(r, 300))
  3. Замокать debounce, чтобы он вызывал функцию сразу
  4. Вместо ??? написать vi.runAllTicks()

Разбор

Фейковые таймеры подменяют setTimeout, и advanceTimersByTime мгновенно прокручивает виртуальное время, выполняя созревшие таймеры. Тест быстрый и детерминированный.

  • await в не-async функции это синтаксическая ошибка, а даже в async-тесте реальное ожидание замедляет набор.
  • Замоканный debounce проверяет мок, а не сам debounce.
  • runAllTicks выполняет очередь process.nextTick, таймеры от этого не продвигаются.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.