如何使用Jest在同一个函数中mock两个不同的日期?
解决方案
你遇到的问题本质是全局Date mock返回固定值,导致函数内两次无参构造Date的结果完全一致,有两种可行方案:
方案1:不修改业务代码,调整Mock逻辑
适合不想改动现有上线代码的场景,通过Mock整个Date构造函数,按调用顺序返回不同值即可:
// 测试用例文件的mock配置 const OriginalDate = Date; beforeAll(() => { // 定义两次无参new Date()依次返回的日期 const mockDates = [ new OriginalDate('2023-01-05T00:00:00Z'), // 第一个new Date()对应today new OriginalDate('2023-01-05T00:00:00Z') // 第二个new Date()对应nextcollectionDate的初始值 ]; let callCount = 0; global.Date = jest.fn((...args) => { // 带参数的Date调用走原生逻辑,避免破坏setDate等内置方法 if (args.length) return new OriginalDate(...args); return mockDates[callCount++]; }); // 继承原生Date的原型和静态方法 global.Date.prototype = OriginalDate.prototype; global.Date.now = jest.fn(() => mockDates[0].getTime()); }); afterAll(() => { // 测试结束恢复原生Date,避免影响其他用例 jest.restoreAllMocks(); });
该方案的缺点是如果后续函数内无参new Date()的顺序/次数变化,mock逻辑需要同步调整,维护成本较高。
方案2:优化函数设计,使用依赖注入(更推荐)
原函数和全局Date强耦合确实会降低可测试性,更合理的写法是把当前日期作为可选参数传入,生产环境不传默认用当前时间,测试环境直接传指定值,完全不需要mock全局对象。
修改后的业务代码:
export const getDateDifference = (collectionDate, today = new Date()) => { // 基于传入的today生成下一个收款日初始值,和原逻辑完全对齐 const nextcollectionDate = new Date(today.getTime()); nextcollectionDate.setDate(collectionDate); const differenceInTime = nextcollectionDate.getTime() - today.getTime(); return (differenceInTime / (1000 * 3600 * 24)).toFixed(0); };
测试用例直接传参即可,无需任何mock:
test('计算1月5号到1月15号的日期差为10', () => { const testToday = new Date('2023-01-05T00:00:00Z'); expect(getDateDifference(15, testToday)).toBe('10'); });
该方案逻辑更清晰,没有全局依赖,测试成本低,后续迭代不容易出问题。
内容的提问来源于stack exchange,提问作者coding1223322
相关产品推荐
相关产品推荐

