如何Mock函数内部调用的new Date()?现有Jest测试用例失败原因是什么?
测试失败的核心原因
- 第一,时区逻辑不统一:你编写的函数里混合了两种时区的取值逻辑:
toISOString()始终返回UTC0时区的标准时间字符串,你示例的mock时间2021-08-04T11:01:58.135Z经过这个方法拆分得到的日期固定是2021-08-04toTimeString()返回的是运行环境本地时区的时间字符串,如果你所在的环境不是UTC0时区(比如国内为东八区),对应时间会是19:01:58,最终返回值就会变成2021-08-04 19:01:58,和你预期的UTC时间小时数不匹配。
- 第二,手动Mock Date的方式有缺陷:直接用
jest.spyOn(global, 'Date').mockImplementation的方式只会覆盖new Date()的返回值,不会修改Date原型方法的时区计算逻辑,也不兼容Date的其他静态方法,很容易出现不可预期的错误。
修复方案
优先使用Jest官方提供的系统时间Mock能力,同时统一函数的时区逻辑:
第一步:调整函数统一用UTC时区取值(如果你的业务需要返回UTC时间)
export const getCurrentTimestamp = () => { const d = new Date(); const date = d.toISOString().split('T')[0]; // 统一取UTC时区的时分秒,补前导零保证格式 const hours = String(d.getUTCHours()).padStart(2, '0') const minutes = String(d.getUTCMinutes()).padStart(2, '0') const seconds = String(d.getUTCSeconds()).padStart(2, '0') return `${date} ${hours}:${minutes}:${seconds}`; };
第二步:调整测试用例用官方API Mock系统时间
test('verifying current timestamp', () => { const mockTime = new Date('2021-08-04T11:01:58.135Z'); // 用官方API替换手动Mock Date jest.useFakeTimers().setSystemTime(mockTime); expect(getCurrentTimestamp()).toBe('2021-08-04 11:01:58'); // 测试结束后恢复真实定时器,避免影响其他用例 jest.useRealTimers(); });
如果你的业务实际需要返回本地时区的时间,只需要把函数里的UTC相关方法替换为普通本地时间方法,同时调整测试的预期值为对应时区的时间即可。
内容的提问来源于stack exchange,提问作者ahkam
相关产品推荐
相关产品推荐

