Jest测试React组件时match属性被覆盖问题求助
问题原因
你的组件用了withRouter高阶组件,它会自动从react-router的路由上下文里注入match、location等属性,手动传入的同名props会被withRouter注入的覆盖,所以你设置的match={{params: {messageId: 123}}}根本不会生效,组件拿到的是路由上下文里默认的根路径match。
解决方法
下面给你三种可行的方案,按需选择:
方案一:用MemoryRouter + Route模拟带参数的路由
这是最贴近真实场景的方案,通过MemoryRouter设置初始路由路径,再用Route匹配路径,让withRouter能拿到正确的match参数。
修改测试代码里的render部分:
import { MemoryRouter, Route } from "react-router-dom"; // 先导入MemoryRouter和Route // 替换原来的render内容 render( <MemoryRouter initialEntries={['/path/123']}> {/* 设置初始路由路径,包含messageId */} <Route path="/path/:messageId"> {/* 匹配带参数的路径 */} <EditPost test={"123"} /> {/* 不用手动传match了 */} </Route> </MemoryRouter> )
这样组件通过withRouter就能拿到match.params.messageId = '123'(注意是字符串类型,和路由路径里的一致)。
方案二:Mock withRouter,让它透传手动传入的props
直接修改react-router-dom的mock,让withRouter不注入自己的match,而是返回我们传入的props:
jest.mock('react-router-dom', () => { const actual = jest.requireActual('react-router-dom'); return { ...actual, useHistory: jest.fn(), useLocation: jest.fn().mockReturnValue({ pathname: '/testpath2', search: '', hash: '', state: {}, key: '5nvxpbdafa', }), withRouter: (Component) => (props) => <Component {...props} /> // 让withRouter直接透传props } });
之后你手动传入的match={{params: {messageId: 123}}}就会生效,不会被覆盖。
方案三:如果组件内部用了useParams,直接mock useParams
如果你的组件除了withRouter,还直接用了useParams() hook获取参数,也可以直接mock这个hook:
jest.mock('react-router-dom', () => { const actual = jest.requireActual('react-router-dom'); return { ...actual, useHistory: jest.fn(), useLocation: jest.fn().mockReturnValue({ pathname: '/testpath2', search: '', hash: '', state: {}, key: '5nvxpbdafa', }), useParams: jest.fn().mockReturnValue({ messageId: '123' }) // 直接返回需要的参数 } });
这种方式更简洁,不需要处理路由组件嵌套。
注意事项
- 用方案一的时候,记得把
BrowserRouter换成MemoryRouter,因为BrowserRouter依赖真实的DOM环境,测试用MemoryRouter更合适。 - 如果你的业务代码里路由路径是
/path/${myMessageId},测试里的Route路径要和业务代码保持一致,不然匹配不到参数。
内容的提问来源于stack exchange,提问作者Prem P.
相关产品推荐
相关产品推荐

