Jasmine — это поведенческий фреймворк для тестирования JavaScript-кода. Он обеспечивает удобный синтаксис для написания юнит-тестов, позволяет создавать изолированные сценарии и поддерживает мокирование времени и зависимостей, что особенно важно при тестировании функций, зависящих от текущей даты и времени.
Date.nowМетод Date.now() возвращает количество миллисекунд,
прошедших с полуночи 1 января 1970 года по UTC. Функции, использующие
Date.now, могут вести себя по-разному в зависимости от
времени вызова, что усложняет тестирование.
Для корректного тестирования важно изолировать источник времени, чтобы результаты были предсказуемыми.
spyOnJasmine предоставляет функцию spyOn, которая позволяет
перехватывать вызовы методов и подменять их поведение. Для
Date.now это выглядит следующим образом:
describe('Функции с Date.now', function() {
it('должна возвращать фиксированное время', function() {
const fixedTime = 1609459200000; // 1 января 2021 года, 00:00:00 UTC
spyOn(Date, 'now').and.returnValue(fixedTime);
const result = Date.now();
expect(result).toBe(fixedTime);
});
});
Ключевые моменты:
spyOn(Date, 'now') создаёт шпион для метода
Date.now.and.returnValue(fixedTime) позволяет задать
фиксированное значение, возвращаемое при вызове.Функции, вычисляющие разницу во времени или поведение по дате, могут быть протестированы с использованием подмены времени:
function isExpired(timestamp) {
return Date.now() > timestamp;
}
describe('isExpired', function() {
it('возвращает true, если текущее время больше указанного', function() {
const futureTime = 1700000000000;
spyOn(Date, 'now').and.returnValue(1700000001000);
expect(isExpired(futureTime)).toBeTrue();
});
it('возвращает false, если текущее время меньше указанного', function() {
const futureTime = 1700000001000;
spyOn(Date, 'now').and.returnValue(1700000000000);
expect(isExpired(futureTime)).toBeFalse();
});
});
Особенности:
isExpired полностью зависит от времени, поэтому
без подмены тесты будут нестабильными.spyOn позволяет контролировать точное значение времени
для проверки всех сценариев.jasmine.clockДля тестирования таймеров и отложенных действий Jasmine предоставляет встроенные часы:
describe('Таймеры с Date.now', function() {
beforeEach(function() {
jasmine.clock().install();
jasmine.clock().mockDate(new Date(2022, 0, 1)); // 1 января 2022 года
});
afterEach(function() {
jasmine.clock().uninstall();
});
it('проверяет отложенное выполнение', function() {
let called = false;
setTimeout(() => { called = true; }, 1000);
jasmine.clock().tick(1000);
expect(called).toBeTrue();
});
it('позволяет получать текущее время через Date.now', function() {
expect(Date.now()).toBe(new Date(2022, 0, 1).getTime());
});
});
Принципы работы с jasmine.clock:
install() заменяет внутренние таймеры и методы времени
шпионами.mockDate() задаёт фиксированную текущую дату, которая
используется всеми методами времени.tick(ms) продвигает виртуальные часы на заданное
количество миллисекунд, что полезно для проверки setTimeout
и setInterval.uninstall() восстанавливает оригинальные таймеры,
предотвращая побочные эффекты.Подмена конкретных методов: Используется
spyOn(Date, 'now'), чтобы фиксировать возвращаемое значение
времени.
Виртуальные часы: jasmine.clock()
позволяет управлять временем для всех таймеров и вызовов
Date.now() одновременно.
Передача времени как параметра: Более чистый
способ — передавать timestamp в функции, чтобы тесты не
зависели от реального времени.
jasmine.clock() для тестирования
отложенных вызовов и анимаций.Тестирование функций с использованием Date.now в Jasmine
позволяет полностью контролировать поведение времени, обеспечивая
надежные и предсказуемые результаты, независимо от реальной даты и
времени выполнения кода.