Mock全局日期时间需替换Date构造函数和Date.now()以固定时间,测试后须还原;涉及定时器时推荐jest.useFakeTimers;可封装工具函数实现灵活开关。

在 JS 项目中,Mock 全局日期时间(如 Date 构造函数、Date.now())主要用于测试时控制时间行为,避免因真实时间变化导致断言失败或逻辑不可控。核心思路是**替换全局 Date 对象的行为**,而非仅 mock 某个函数调用。
直接覆盖全局 Date 构造函数和静态方法
这是最常用且兼容性好的方式,尤其适合单元测试(如 Jest、Vitest)或开发调试阶段。关键点是:必须在测试/模拟逻辑执行前完成覆盖,且注意还原以避免污染其他测试。
- 重写
Date构造函数,使其始终返回指定时间(如固定时间戳对应的 Date 实例) - 重写
Date.now,返回固定时间戳(毫秒数),影响所有依赖它的逻辑(如new Date()、performance.now()通常不受影响) - 可选:覆盖
Date.parse和原型方法(如toISOString)以确保格式一致性,但多数场景只需构造函数 +now
示例(Jest 中):
// 测试开始前
const fixedTimestamp = new Date('2023-01-01T12:00:00Z').getTime();
<p>jest.mock('./some-module', () => ({ /<em> mock 其他依赖 </em>/ }));</p><p>beforeEach(() => {
// 保存原始 Date
const OriginalDate = global.Date;</p><p>// 覆盖全局 Date
global.Date = class extends OriginalDate {
constructor(...args) {
if (args.length === 0) {
// new Date() → 固定时间
super(fixedTimestamp);
} else {
// new Date(arg) → 原行为(保持灵活性)
super(...args);
}
}
};</p><p>// 覆盖 Date.now
global.Date.now = jest.fn(() => fixedTimestamp);
});</p><p>afterEach(() => {
// 还原原始 Date,防止干扰其他测试
global.Date = global.Date['mockRestore'] ? undefined : global.Date;
delete global.Date.now;
});
使用 Sinon 或 jest.useFakeTimers 管理时间(推荐用于集成/定时逻辑)
当需要模拟时间流逝(如 setTimeout、setInterval、或验证“3 秒后触发”逻辑)时,jest.useFakeTimers 更合适。它不仅 mock 时间获取,还接管定时器调度。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
-
jest.useFakeTimers('modern')(Jest 27+)会自动 mockDate、performance.now、setTimeout等 - 调用
jest.setSystemTime(timestamp)即可统一设定“当前系统时间” - 配合
jest.advanceTimersByTime(ms)可推进时间,触发延迟回调
示例:
beforeEach(() => {
jest.useFakeTimers('modern');
jest.setSystemTime(new Date('2023-01-01T12:00:00Z'));
});
<p>test('should format date correctly', () => {
expect(new Date().toISOString()).toBe('2023-01-01T12:00:00.000Z');
});</p><p>test('should call callback after 2s', () => {
const callback = jest.fn();
setTimeout(callback, 2000);
expect(callback).not.toBeCalled();
jest.advanceTimersByTime(2000);
expect(callback).toBeCalled();
});
封装成可复用的 Mock 工具函数
为避免重复代码,可封装一个临时 mock 时间的工具,支持快速启用/恢复,适用于非测试环境(如本地调试、Storybook)。
function mockGlobalDate(fixedDate) {
const timestamp = typeof fixedDate === 'number'
? fixedDate
: new Date(fixedDate).getTime();
<p>const originalDate = global.Date;</p><p>global.Date = class extends originalDate {
constructor(...args) {
if (args.length === 0) super(timestamp);
else super(...args);
}
};</p><p>global.Date.now = () => timestamp;</p><p>return () => {
global.Date = originalDate;
delete global.Date.now;
};
}</p><p>// 使用
const restore = mockGlobalDate('2023-01-01');
// ... 执行被测代码
restore(); // 恢复
注意事项与常见陷阱
-
不要只 mock 某个模块里的 Date 引用:如果模块写了
import { Date } from 'some-lib'或const Date = global.Date,需确保 mock 的是实际被使用的对象 -
ESM 环境下不能直接赋值 global.Date:Vite / Webpack 等打包器可能将
Date视为不可写全局,此时应优先用jest.useFakeTimers或在入口处通过Object.defineProperty强制覆盖 -
第三方库可能缓存 Date:比如某些工具库启动时读取一次
Date.now()并缓存,这种需在 mock 后重新初始化库 -
Node.js 与浏览器差异:Node 中
global.Date可直接改;浏览器中是window.Date,但测试环境(Jest)默认运行在 jsdom,仍用global
不复杂但容易忽略。关键是根据使用场景选对方式:纯时间值固定 → 覆盖构造函数;涉及延时/定时器 → 用 fake timers;需要灵活开关 → 封装 restore 函数。

















