Установка и удаление clock

Jasmine предоставляет возможность контролировать время и таймеры через встроенный объект clock, что позволяет тестировать асинхронные операции, зависящие от таймеров, без фактического ожидания. Работа с clock особенно актуальна при использовании функций setTimeout, setInterval и методов, взаимодействующих с временем.

Подключение и установка clock

Перед началом работы с объектом clock необходимо его установить с помощью метода jasmine.clock().install(). Этот вызов перехватывает все встроенные таймеры JavaScript, перенаправляя их управление на Jasmine:

beforeEach(function() {
  jasmine.clock().install();
});

Особенности установки:

  • Метод install() необходимо вызывать перед каждым тестом, где планируется использование clock.
  • После установки любые вызовы setTimeout, setInterval или Date будут управляться Jasmine, что позволяет управлять их выполнением в тестах без фактической задержки времени.
  • Clock можно настроить для имитации текущего времени:
const baseTime = new Date(2026, 0, 11, 10, 0, 0);
jasmine.clock().mockDate(baseTime);

В этом случае объект Date будет возвращать указанное время, а не системное.

Продвижение времени

После установки clock, таймеры не запускаются автоматически. Чтобы заставить их выполниться, используется метод tick:

setTimeout(function() {
  console.log("Таймер сработал");
}, 1000);

jasmine.clock().tick(1000);

Метод tick(ms) ускоряет внутреннее время Jasmine на указанное количество миллисекунд, что позволяет тестировать задержки и интервалы без фактического ожидания.

Важно: tick() работает только после установки clock. Любые вызовы таймеров до install() будут использовать реальные системные таймеры.

Удаление clock

После завершения теста необходимо вернуть оригинальные таймеры и объект Date в нормальное состояние. Для этого используется метод:

afterEach(function() {
  jasmine.clock().uninstall();
});

Примечания по удалению:

  • uninstall() восстанавливает все перехваченные таймеры и объект Date.
  • Пропуск вызова uninstall() может привести к непредсказуемому поведению последующих тестов, так как они будут использовать уже модифицированные таймеры.
  • Если требуется использовать clock только в отдельных тестах, установка и удаление должны производиться в beforeEach и afterEach соответственно.

Совместная работа с асинхронными функциями

Clock позволяет тестировать асинхронные операции без использования промисов или реальных задержек. Например:

function delayedCallback(callback) {
  setTimeout(callback, 2000);
}

describe('Тестирование delayedCallback', function() {
  beforeEach(function() {
    jasmine.clock().install();
  });

  afterEach(function() {
    jasmine.clock().uninstall();
  });

  it('должен вызвать callback через 2 секунды', function() {
    const callback = jasmine.createSpy('callback');
    delayedCallback(callback);

    jasmine.clock().tick(1999);
    expect(callback).not.toHaveBeenCalled();

    jasmine.clock().tick(1);
    expect(callback).toHaveBeenCalled();
  });
});

В этом примере таймеры полностью контролируются Jasmine, а проверка вызывается без реальной задержки времени.

Моделирование времени с mockDate

Метод mockDate позволяет задать фиксированное текущее время для всех объектов Date:

const fixedTime = new Date(2026, 0, 11, 12, 0, 0);
jasmine.clock().mockDate(fixedTime);

console.log(new Date().toString()); // Всегда выводит фиксированное время

Это полезно для тестирования функций, которые зависят от времени суток, дат или временных интервалов, например логирования или формирования отчетов.

Рекомендации по использованию

  • Всегда устанавливать clock только там, где необходим контроль времени.
  • После каждого теста возвращать оригинальные таймеры через uninstall.
  • Для имитации текущего времени использовать mockDate.
  • Для проверки последовательности таймеров использовать метод tick с точными значениями времени.
  • Не смешивать реальное время и Jasmine clock внутри одного теста, чтобы избежать непредсказуемого поведения.

Использование jasmine.clock() позволяет создавать предсказуемые, быстрые и надежные тесты для кода, зависящего от таймеров и текущей даты, полностью исключая необходимость фактического ожидания.