В процессе тестирования JavaScript-приложений часто возникает
необходимость управлять временем: проверять поведение кода в разные
моменты, фиксировать текущую дату для предсказуемых результатов или
эмулировать истечение таймеров. Библиотека MockDate
позволяет надежно контролировать объект Date, создавая
предсказуемую среду для тестов. В сочетании с Jasmine,
MockDate становится мощным инструментом для юнит-тестирования кода,
зависящего от времени.
Для использования MockDate в проекте достаточно установить библиотеку через npm:
npm install mockdate --save-dev
После установки подключение в тестах Jasmine осуществляется стандартным способом:
const MockDate = require('mockdate');
Для браузерных сред возможна загрузка через
<script> из CDN:
<script src="https://unpkg.com/mockdate"></script>
После подключения библиотека предоставляет методы для установки фиксированной даты и возврата системы к текущему времени.
1. Установка фиксированной даты
Метод MockDate.set(date, [timezoneOffset]) позволяет
задать конкретную дату. date может быть строкой, числом
(timestamp) или объектом Date.
MockDate.set('2026-01-11T12:00:00Z');
console.log(new Date().toISOString()); // 2026-01-11T12:00:00.000Z
Необязательный параметр timezoneOffset задает смещение
часового пояса в минутах:
MockDate.set('2026-01-11T12:00:00Z', -120); // GMT+2
2. Сброс даты к реальному времени
Для возврата нормальной работы объекта Date используется
метод MockDate.reset():
MockDate.reset();
console.log(new Date()); // текущая реальная дата
В Jasmine удобно использовать MockDate внутри хуков
beforeEach и afterEach, чтобы каждый тест имел
предсказуемое состояние времени, а после завершения теста среда
возвращалась к нормальному состоянию.
describe('Примеры работы с датой', () => {
beforeEach(() => {
MockDate.set('2026-01-11T12:00:00Z');
});
afterEach(() => {
MockDate.reset();
});
it('возвращает фиксированное время', () => {
const now = new Date();
expect(now.toISOString()).toBe('2026-01-11T12:00:00.000Z');
});
it('позволяет изменять время внутри теста', () => {
MockDate.set('2026-01-12T15:30:00Z');
expect(new Date().toISOString()).toBe('2026-01-12T15:30:00.000Z');
});
});
Использование хуков позволяет изолировать состояние времени для каждого теста и предотвращает побочные эффекты между тестами.
Когда код зависит от задержек (setTimeout,
setInterval) или вычисляет разницу между датами, MockDate
позволяет управлять временем без реального ожидания.
describe('Тестирование задержек', () => {
it('вычисляет разницу между датами', () => {
MockDate.set('2026-01-11T12:00:00Z');
const start = new Date();
MockDate.set('2026-01-11T12:05:00Z'); // прошло 5 минут
const end = new Date();
const diffMinutes = (end - start) / 60000;
expect(diffMinutes).toBe(5);
});
});
Такой подход особенно полезен для тестирования функций, которые зависят от текущего времени, например, проверка истечения токенов, планировщиков задач или ограничений по времени.
Jasmine предоставляет метод spyOn для подмены функций.
MockDate можно сочетать с этим инструментом для проверки вызовов функций
с точным временем.
describe('Интеграция с spyOn', () => {
it('вызывает функцию с текущей датой', () => {
const logger = { logTime: () => new Date() };
spyOn(logger, 'logTime').and.callThrough();
MockDate.set('2026-01-11T12:00:00Z');
logger.logTime();
expect(logger.logTime).toHaveBeenCalled();
expect(logger.logTime()).toEqual(new Date('2026-01-11T12:00:00Z'));
});
});
Такое сочетание обеспечивает точный контроль времени и проверку логики, зависящей от даты.
beforeEach и afterEach
для предотвращения побочных эффектов.timezoneOffset.afterEach, чтобы
избежать влияния на другие тесты.jasmine.clock() для полного контроля времени и
задержек.MockDate превращает работу с временем в тестах из потенциально хаотичного процесса в строго контролируемый, обеспечивая стабильность и предсказуемость результатов тестирования.