如何用Jest模拟Date()修改Vue中export default外的常量日期
问题分析
你遇到的核心问题是:模块级变量formatCurrentDate在组件模块加载阶段就已执行计算,而Jest的jest.useFakeTimers()和jest.setSystemTime()是在beforeEach中才设置的——这时候组件模块已经加载完成,formatCurrentDate早就用真实时间计算好了,自然不会受后续fake timers的影响。
而data中的currentDate是在组件初始化时执行的,此时beforeEach已经完成fake timers的设置,所以能正确拿到mock的系统时间。
解决方案
提供两种可行方案,根据你的实际场景选择:
方案1:修改Vue组件代码,延迟formatCurrentDate的计算时机
把模块级的直接赋值改成函数,或者将其移入组件的计算属性/生命周期钩子,确保它在组件初始化(此时fake timers已生效)后再执行:
<script> import dateFormat from 'dateformat'; // 改成函数,需要使用时再调用 const getFormatCurrentDate = () => dateFormat(new Date(), 'yyyy/mm/dd'); export default { data() { // 注意:原代码data选项缺少return,这是Vue单文件组件的错误写法,必须修正 return { currentDate: dateFormat(new Date(), 'yyyy-mm-dd'), }; }, // 如果formatCurrentDate需要在组件模板或逻辑中使用,推荐用计算属性 computed: { formatCurrentDate() { return dateFormat(new Date(), 'yyyy/mm/dd'); } } }; </script>
这样在测试时,只要组件初始化完成,调用getFormatCurrentDate()或者访问formatCurrentDate计算属性,都会使用mock的系统时间。
方案2:在测试文件中提前设置fake timers(在导入组件前)
模块导入是同步执行的,所以要在导入组件之前就配置好fake timers和mock时间,确保组件模块加载时formatCurrentDate的计算能用到mock时间:
const systemDate = new Date('2022-06-23 13:29:00'); // 关键:先设置fake timers和系统时间,再导入组件 jest.useFakeTimers(); jest.setSystemTime(systemDate); // 此时导入组件,模块级的formatCurrentDate会用mock时间计算 import YourVueComponent from '@/path/to/your/component.vue'; afterAll(() => { jest.useRealTimers(); }); // 若有多个测试用例,可在beforeEach中重置系统时间 beforeEach(() => { jest.setSystemTime(systemDate); }); // 测试用例示例 test('formatCurrentDate uses mocked date', () => { // 假设formatCurrentDate是组件模块导出的变量(若要访问需确保它被导出) expect(YourVueComponent.__moduleExports.formatCurrentDate).toBe('2022/06/23'); });
额外提示
原Vue组件的data选项写法有误:data必须是一个返回对象的函数,否则多个组件实例会共享同一份数据。请务必修正为带return的写法,避免后续出现意外问题。
内容的提问来源于stack exchange,提问作者Seok Loi
相关产品推荐
相关产品推荐

