Jest 测试移动端组件时怎么模拟触摸事件?

Air-利云 阅读 41

我用 Jest + React Testing Library 写测试,但有个组件依赖 onTouchStart 事件,本地跑测试一直不触发。试过 fireEvent.touchStart,但报错说方法不存在,是不是得用别的 API?

查了文档没找到明确例子,有人在移动端测试里成功模拟过 touch 事件吗?

我来解答 赞 9 收藏
二维码
手机扫码查看
2 条解答
玉宁 Dev
试试这个,fireEvent 不支持 touchStart,用 container.dispatchEvent 手动派发事件吧

const touchEvent = new TouchEvent('touchstart', {
touches: [new Touch({ identifier: 1, target: element, clientX: 0, clientY: 0 })]
});
element.dispatchEvent(touchEvent);
点赞
2026-03-21 15:12
A. 红敏
A. 红敏 Lv1
这个问题很常见,React Testing Library 的 fireEvent 默认没有 touchStart、touchEnd 这些方法,得自己动手造。

直接上代码:

// 先创建一个辅助函数
const createTouchEvent = (eventName, options = {}) => {
const event = new TouchEvent(eventName, {
bubbles: true,
cancelable: true,
touches: options.touches || [],
targetTouches: options.targetTouches || [],
changedTouches: options.changedTouches || [],
...options
});
return event;
};

// 测试里这样用
test('触摸事件正常触发', () => {
const handleTouchStart = jest.fn();
render(
测试元素
);

const element = screen.getByText('测试元素');

// 触发 touchStart
const touchEvent = createTouchEvent('touchStart', {
touches: [{ clientX: 100, clientY: 100, identifier: 0 }],
changedTouches: [{ clientX: 100, clientY: 100, identifier: 0 }]
});
element.dispatchEvent(touchEvent);

expect(handleTouchStart).toHaveBeenCalled();
});


如果你用的是比较新的 jsdom(14+),TouchEvent 构造函数本身可能不存在,需要 polyfill。可以在测试文件开头加:

// jest.setup.js 或测试文件顶部
if (typeof TouchEvent === 'undefined') {
global.TouchEvent = class TouchEvent extends Event {
constructor(type, options) {
super(type, options);
this.touches = options?.touches || [];
this.targetTouches = options?.targetTouches || [];
this.changedTouches = options?.changedTouches || [];
}
};
}


另外提醒一下,如果你测试的目标是移动端组件,很多情况下用 click 事件或者 mouse 事件也能覆盖到大部分场景,除非你的组件确实依赖 touch 的特定属性(比如 touches 数组、clientX/Y 这些),否则可以考虑是不是真的需要测 touch 事件。
点赞
2026-03-18 07:02