javascript单元测试中mock日期时间的核心是控制date构造函数或date.now()行为,确保测试可重复稳定;常用方法包括覆盖全局date、mock date.now()、使用jest-date-mock库,并需注意避免共享状态、兼顾两者独立性及typescript类型处理。

在 JavaScript 单元测试中 Mock 日期时间对象,核心是控制 Date 构造函数或其静态方法(如 Date.now())的行为,让测试不依赖真实系统时间,从而保证可重复性和稳定性。
直接替换全局 Date 构造函数
最常用、最直接的方式是临时覆盖全局 Date,使其返回固定时间。适用于测试依赖 new Date() 或 Date() 调用的代码。
- 在测试前用
jest.mock(Jest)或手动赋值重写Date - 推荐在
beforeEach中 mock,在afterEach中还原,避免污染其他测试 - 示例(Jest):
const originalDate = global.Date;
beforeEach(() => {
global.Date = class extends Date {
constructor(...args) {
if (args.length === 0) {
super('2023-01-01T12:00:00Z'); // 固定时间
} else {
super(...args);
}
}
};
});
afterEach(() => {
global.Date = originalDate;
});
Mock Date.now() 静态方法
很多逻辑使用 Date.now() 获取毫秒时间戳(例如节流、缓存过期判断),这时只需 mock 该静态方法即可,更轻量且不影响 new Date() 的其他用途。
- Jest 中可直接用
jest.spyOn(Date, 'now').mockReturnValue(1672545600000) - 注意:必须用
mockReturnValue(不是mockImplementation),因为Date.now是 getter-like 静态方法 - 测试结束后调用
mockRestore()恢复原行为
使用专门的 mock 库(如 jest-date-mock)
对复杂时间场景(如“前进/后退时间”、“冻结某段时间”),手动 mock 易出错。可借助成熟库简化操作。
-
jest-date-mock提供advanceTo、freeze、unfreeze等语义化 API - 安装后只需
import 'jest-date-mock';即可全局生效(Jest 环境) - 适合测试定时器、倒计时、时间差计算等逻辑
避免常见陷阱
Mock 时间看似简单,但几个细节容易导致测试失效或行为异常:
- 不要只 mock 构造函数却不处理
Date.now()—— 两者独立,需按需分别控制 - 避免在
describe外层 mock,否则可能被多个测试用例共享状态 - 若被测代码用了
new Date(Date.now())这类写法,仅 mock 构造函数不够,Date.now()仍会返回真实时间 - TypeScript 用户注意:mock 后需类型断言或声明合并,否则类型检查可能报错
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











