javascript单元测试mock系统时间戳需三步:1.手动重写date.now()返回固定值;2.继承并替换global.date以支持new date()调用;3.配合jest fake timers(jest.usefaketimers+setsystemtime)同步控制定时器与时间戳。

JavaScript 单元测试中 Mock 系统时间戳,核心是让 Date.now() 和 new Date() 返回可预测的固定值,避免测试因真实时间漂移而失败或不稳定。
手动 Mock Date.now()
这是最轻量、最直接的方式,适用于只需控制时间戳数值的场景:
- 在
beforeEach中重写Date.now为返回固定毫秒数的函数 - 保存原始方法,确保
afterEach能恢复,防止污染其他测试 - 例如:固定返回 2024-05-30 00:00:00 对应的时间戳
1717027200000
const originalNow = Date.now;
beforeEach(() => {
Date.now = jest.fn(() => 1717027200000);
});
afterEach(() => {
Date.now = originalNow;
});
Mock new Date() 构造函数(更通用)
当业务中使用 new Date()、new Date('2024-01-01') 或依赖其字符串格式时,仅 Mock Date.now() 不够。需替换整个 global.Date 类:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 继承原生
Date,重写构造逻辑:无参调用时返回固定时间;有参时委托给原生行为 - 覆盖
toString、toISOString等方法,确保格式一致(如需要) - 同样需在
afterEach恢复原始Date
const originalDate = global.Date;
beforeEach(() => {
global.Date = class extends originalDate {
constructor(...args) {
if (args.length === 0) {
super('2024-05-30T00:00:00.000Z');
} else {
super(...args);
}
}
};
});
afterEach(() => {
global.Date = originalDate;
});
配合 Jest 的 fake timers(定时器 + 时间戳协同)
若测试同时涉及 setTimeout、setInterval 和时间计算(如倒计时、过期判断),建议启用 Jest 的假定时器机制:
- 调用
jest.useFakeTimers()拦截所有定时器,并统一推进虚拟时间 - 注意:
fake timers默认不接管Date,所以仍需单独 MockDate.now()或global.Date - 推进时间后,
Date.now()应同步变化——此时推荐用jest.setSystemTime(ms)(Jest 29+),它会自动同步影响Date.now()和new Date()
beforeEach(() => {
jest.useFakeTimers();
jest.setSystemTime(new Date('2024-05-30T00:00:00.000Z'));
});
afterEach(() => {
jest.useRealTimers();
});
验证是否生效
不要只看逻辑结果,要主动断言时间相关行为:
- 检查
Date.now()是否返回预期值:expect(Date.now()).toBe(1717027200000) - 检查
new Date().toISOString()格式是否符合预期 - 若逻辑中基于时间差做判断(如
now - createdAt > 3600000),构造对应时间点并验证分支是否触发
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










