如何使用Jest对React组件中history.push的onClick函数做单元测试?
React组件onClick事件单元测试问题
问题背景
需要对以下React组件中的Add按钮onClick函数做Jest单元测试,但现有测试代码报错。
组件代码
const baseURL = "/Security/Users/"; return ( <div> <div className="flex-between"> <button className="bt-save" onClick={() => history.push(baseURL + "Add")} > Add </button> </div> </div> );
现有测试代码
it('Should run the callback function when clicked', async () => { const onClick = jest.fn(baseURL + "Add") render(<button push={onClick}> Add </button>) const addButton = screen.getByText('Add') await userEvent.click(addButton) expect(onClick).toHaveBeenCalled() })
错误原因分析
- 测试逻辑脱离组件实际逻辑:原组件按钮的
onClick是调用history.push,但测试代码手动创建了一个带push属性的假按钮,没有渲染真实组件,完全偏离了测试目标。 jest.fn用法错误:jest.fn()接受函数作为默认实现参数,你传入字符串的写法完全不符合API规范。- 未处理组件依赖的
history对象:组件依赖React Router的history对象,测试环境中未模拟该依赖,导致逻辑无法正常执行。
正确测试方案
方案一:使用MemoryRouter(贴近真实路由场景)
通过React Router提供的MemoryRouter模拟路由环境,直接验证跳转后的路径:
import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { MemoryRouter } from 'react-router-dom'; import YourComponent from './YourComponent'; // 替换为你的组件实际路径 it('点击Add按钮后跳转到正确的添加页面', async () => { render( <MemoryRouter> <YourComponent /> </MemoryRouter> ); const addButton = screen.getByText('Add'); await userEvent.click(addButton); // 验证当前路由路径是否符合预期 expect(window.location.pathname).toBe('/Security/Users/Add'); });
方案二:Mock useHistory钩子
如果组件通过useHistory钩子获取history对象,可以直接mock该钩子来验证方法调用:
import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { useHistory } from 'react-router-dom'; import YourComponent from './YourComponent'; // Mock react-router-dom的useHistory钩子 jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useHistory: jest.fn(), })); it('点击Add按钮时调用history.push并传入正确路径', async () => { const mockPush = jest.fn(); // 让useHistory返回包含mock方法的history对象 useHistory.mockReturnValue({ push: mockPush }); render(<YourComponent />); const addButton = screen.getByText('Add'); await userEvent.click(addButton); // 验证push方法被正确调用,参数符合预期 expect(mockPush).toHaveBeenCalledWith('/Security/Users/Add'); });
内容的提问来源于stack exchange,提问作者Dasun sucharith
相关产品推荐
相关产品推荐

