Jest测试中如何正确mock window对象的ontouchstart事件
问题原因
你之前的写法报错,核心原因是 Jest 默认使用的 jsdom 测试环境初始化时,window 对象上默认不存在ontouchstart属性,而jest.spyOn只能监听对象上已经存在的属性,自然会触发「属性不存在」的编译/运行错误。
另外你的待测试逻辑是通过'ontouchstart' in window做存在性判断,根本不需要对属性做方法实现的mock,只要让属性挂载到window上就能命中对应判断分支。
可直接运行的测试代码
1. 测试命中ontouchstart判断的分支
it('returns true when ontouchstart exists on window', () => { // 直接给window挂载属性即可,in操作符只判断属性是否存在,和具体值无关 window.ontouchstart = jest.fn(); expect(main()).toBe(true); // 测试完成后删除属性,避免污染其他测试用例 delete window.ontouchstart; });
2. 测试命中maxTouchPoints判断的分支
注意navigator.maxTouchPoints是只读属性,不能直接赋值修改,需要通过Object.defineProperty重写:
it('returns true when navigator.maxTouchPoints is greater than 0', () => { // 先清除ontouchstart避免分支判断干扰 delete window.ontouchstart; // 重写只读属性 Object.defineProperty(navigator, 'maxTouchPoints', { configurable: true, value: 2 }); expect(main()).toBe(true); // 测试完成还原默认值 Object.defineProperty(navigator, 'maxTouchPoints', { configurable: true, value: 0 }); });
3. 测试无触摸支持的返回false分支
it('returns false when no touch support is detected', () => { delete window.ontouchstart; Object.defineProperty(navigator, 'maxTouchPoints', { configurable: true, value: 0 }); expect(main()).toBe(false); });
注意事项
- 如果你使用TypeScript编写测试,给window挂载
ontouchstart时可能报类型错误,可在对应行加// @ts-ignore忽略,或者在测试文件的全局类型声明里扩展Window接口添加ontouchstart的类型定义即可。 - 所有手动修改的window、navigator属性一定要在用例执行完成后还原/删除,否则会污染同文件下的其他测试用例,导致用例结果偶发不符合预期。
内容的提问来源于stack exchange,提问作者Dujard
相关产品推荐
相关产品推荐

