如何使用Jest和Enzyme为React组件的window keydown事件编写单元测试
使用Jest和Enzyme测试ESC键触发unfocus函数的功能
我会分场景带你完成这个测试,你可以根据组件的实际实现来选择对应的方案:
1. 基础场景:组件监听全局document的keydown事件
如果你的组件是通过生命周期(比如useEffect)在挂载时给document添加ESC键监听,那可以这么测:
测试步骤拆解
- 先用Jest创建一个mock函数作为
unfocusprops,方便追踪它的调用情况 - 用Enzyme的
mount渲染组件(因为要处理全局事件监听,shallow渲染可能无法覆盖生命周期的副作用) - 模拟document上的ESC键按下事件
- 断言mock函数被正确调用
测试代码示例
import React from 'react'; import { mount } from 'enzyme'; import MyComponent from './MyComponent'; describe('MyComponent ESC key behavior', () => { it('triggers unfocus when Escape key is pressed globally', () => { // 1. 创建mock的unfocus函数 const mockUnfocus = jest.fn(); // 2. 挂载组件并传入mock函数 mount(<MyComponent unfocus={mockUnfocus} />); // 3. 模拟ESC键的keydown事件 const escKeyEvent = new KeyboardEvent('keydown', { key: 'Escape' }); document.dispatchEvent(escKeyEvent); // 4. 验证函数被调用一次 expect(mockUnfocus).toHaveBeenCalledTimes(1); }); it('does NOT trigger unfocus when other keys are pressed', () => { const mockUnfocus = jest.fn(); mount(<MyComponent unfocus={mockUnfocus} />); // 模拟Enter键按下 const enterKeyEvent = new KeyboardEvent('keydown', { key: 'Enter' }); document.dispatchEvent(enterKeyEvent); // 验证函数未被调用 expect(mockUnfocus).not.toHaveBeenCalled(); }); });
2. 组件内部元素监听keydown的场景
如果你的组件是给内部某个可聚焦元素(比如带tabIndex的div、input)绑定keydown事件,测试方式会略有不同:
假设组件代码示例
import React from 'react'; const MyComponent = ({ unfocus }) => { const handleKeyDown = (e) => { if (e.key === 'Escape') { unfocus(); } }; return <div tabIndex={0} onKeyDown={handleKeyDown}>Click to focus</div>; };
对应测试代码
import React from 'react'; import { shallow } from 'enzyme'; import MyComponent from './MyComponent'; describe('MyComponent ESC key behavior', () => { it('triggers unfocus when Escape key is pressed on the component element', () => { const mockUnfocus = jest.fn(); const wrapper = shallow(<MyComponent unfocus={mockUnfocus} />); // 找到目标元素,模拟keydown事件 wrapper.find('div').simulate('keydown', { key: 'Escape' }); expect(mockUnfocus).toHaveBeenCalledTimes(1); }); });
3. 测试注意事项
- 若使用React 18+,需要安装适配的Enzyme适配器(比如
@wojtekmaj/enzyme-adapter-react-18)并在测试文件头部配置 - 全局事件测试后建议清理,避免影响其他测试:
afterEach(() => { jest.clearAllMocks(); }); - 模拟事件时如果需要事件冒泡,记得添加
bubbles: true参数:const escKeyEvent = new KeyboardEvent('keydown', { key: 'Escape', bubbles: true });
内容的提问来源于stack exchange,提问作者Jinto
相关产品推荐
相关产品推荐

