React Router V4下React登录组件Jest+Enzyme浅测试问题
解决React Router V4 + Jest/Enzyme浅测试中
history.push的报错问题 刚好我之前也踩过这个坑,你的问题根源很明确:登录组件依赖React Router注入的history props,但在浅渲染测试时,这个props并没有被自动提供,所以调用this.props.history.push就会抛出错误。下面给你几个实用的解决方案,按需选择就行:
方案1:手动Mock history props(推荐浅测试使用)
这种方法最直接,不用引入任何Router相关组件,直接给测试组件传入一个mock的history对象,专注测试组件的业务逻辑:
import { shallow } from 'enzyme'; import Login from './Login'; describe('Login Component', () => { it('triggers redirect on successful login', () => { // 创建一个mock的history,用jest.fn()来追踪方法调用 const mockHistory = { push: jest.fn() }; // 把mock的history作为props传入组件 const wrapper = shallow(<Login history={mockHistory} />); // 模拟登录提交操作(根据你的组件结构调整选择器和事件) wrapper.find('form').simulate('submit', { preventDefault: () => {} }); // 验证history.push是否被正确调用 expect(mockHistory.push).toHaveBeenCalledWith('/'); }); });
方案2:用MemoryRouter包裹组件(适合完整集成测试)
如果你想模拟更贴近真实环境的路由行为,可以使用React Router提供的MemoryRouter来包裹组件,这样组件就能自动获取到正确的history props。注意这种方法适合用mount渲染(浅渲染shallow不会渲染MemoryRouter的子组件):
import { mount } from 'enzyme'; import { MemoryRouter } from 'react-router-dom'; import Login from './Login'; describe('Login Component', () => { it('redirects to home after login', () => { const wrapper = mount( <MemoryRouter> <Login /> </MemoryRouter> ); // 模拟登录提交 wrapper.find('form').simulate('submit', { preventDefault: () => {} }); // 获取组件的history props,验证路由跳转结果 const loginComponent = wrapper.find(Login); expect(loginComponent.props().history.location.pathname).toBe('/'); }); });
方案3:用withRouter包装组件(适配非路由直接渲染的组件)
如果你的Login组件不是直接放在Route组件内部渲染的,而是作为普通组件被调用,那么可以用withRouter高阶组件包装它,确保它能获取到Router相关的props:
组件代码调整:
import React from 'react'; import { withRouter } from 'react-router-dom'; class Login extends React.Component { // 你的组件逻辑,比如登录成功后调用this.props.history.push('/') } // 用withRouter包装组件后导出 export default withRouter(Login);
之后测试时,就可以用上面两种方案中的任意一种来处理。
内容的提问来源于stack exchange,提问作者Dan Zuzevich
相关产品推荐
相关产品推荐

