在reducer初始状态使用Date.now()导致Jest测试用例失败如何解决?
问题根因
- 你在reducer文件和测试文件中分别定义了两个独立的
INITIAL_STATE,两者的Date.now()执行时机不同,生成的时间戳自然存在毫秒级差异 toBe是全等匹配,用于对比对象时校验的是内存引用地址,即使两个对象值完全一致也会判定不相等,仅当两个变量指向同一个对象时才会通过校验
解决方案
方案1:直接复用reducer导出的初始状态(最简单)
首先修改reducer代码,导出内部定义的初始状态:
// reducer代码 export const INITIAL_STATE = { scroll: Date.now(), }; export default function clearStore(state = INITIAL_STATE, action) { switch (action.type) { case CLEAR_STORE: { return INITIAL_STATE } default: return state; } }
修改测试代码,直接导入reducer暴露的初始状态,同时将匹配方法改为toEqual校验值相等:
import clearStore, { INITIAL_STATE } from "./clear-store"; it("testing default case", () => { const newState = clearStore(undefined, {}); expect(newState).toEqual(INITIAL_STATE); })
方案2:Mock固定时间戳(适合需要校验固定时间值的场景)
通过Jest mockDate.now的返回值,保证两个文件执行时拿到的时间固定,注意要先mock再导入reducer,避免reducer模块加载时已经执行了原始的Date.now:
// 测试代码 const fixedTime = 1633947823739; jest.spyOn(Date, 'now').mockReturnValue(fixedTime); // 先mock再导入reducer import clearStore from "./clear-store"; it("testing default case", () => { const newState = clearStore(undefined, {}); expect(newState.scroll).toBe(fixedTime); // 测试完成后恢复原始方法,避免影响其他用例 Date.now.mockRestore(); })
方案3:校验字段类型/范围(不需要固定时间值的场景)
如果你的测试逻辑不需要校验具体时间值,只需要确认字段存在且格式正确,可以直接做类型校验:
it("testing default case", () => { const newState = clearStore(undefined, {}); // 校验是数字类型 expect(typeof newState.scroll).toBe('number'); // 也可以校验时间范围,误差在1秒内即可 expect(newState.scroll).toBeGreaterThanOrEqual(Date.now() - 1000); })
内容的提问来源于stack exchange,提问作者T R
相关产品推荐
相关产品推荐

