如何用Jest和Enzyme测试含Router、Redux及两个HOC的React组件?
解决React组件被HOC包裹后测试仅显示Route的问题
看起来你遇到的问题核心是组件被HOC包裹后默认导出,导致测试时无法直接访问原组件,而且这个withFetch HOC内部应该集成了React Router的Route逻辑,所以你看到的快照只有<Route render={[Function: render]} />。我给你几个可行的解决思路:
1. 给原组件添加命名导出(最推荐)
你现在的组件只有被withFetch处理后的默认导出,所以导入{ Component }会返回undefined。修改原组件文件,同时导出未被HOC处理的原始组件:
// 你的组件文件 export class MyComponent extends React.Component { // 组件的核心逻辑 } // 保持原有的默认导出,供业务代码使用 export default withFetch(MyComponent)(fetchData, mapStateToProps);
这样在测试文件里,你就可以直接导入原始组件进行测试:
import { MyComponent } from './components/'; it('should render self and subcomponents', () => { const wrapper = shallow(<MyComponent {...props} />); expect(toJson(wrapper)).toMatchSnapshot(); });
这种方式最直接,因为测试的是组件本身,不需要处理HOC和路由、Redux的依赖。
2. 模拟HOC,让它直接返回原组件
如果暂时无法修改原组件的导出,可以用Jest的mock功能绕过withFetch的处理:
// 在测试文件顶部添加 jest.mock('./path/to/withFetch', () => { // 模拟HOC,直接返回传入的组件 return (Component) => () => Component; }); // 此时导入的默认导出就是原组件 import Component from './components/'; it('should render self and subcomponents', () => { const wrapper = shallow(<Component {...props} />); expect(toJson(wrapper)).toMatchSnapshot(); });
3. 正确配置环境,测试被HOC包裹后的组件
如果你需要测试完整的HOC包裹后的组件(包括路由、Redux逻辑),需要把组件放在正确的上下文环境中,并且用mount而不是shallow:
import { Provider } from 'react-redux'; import { MemoryRouter } from 'react-router-dom'; import configureStore from './your-store-config-path'; // 你的Redux store配置文件 import Component from './components/'; const mockStore = configureStore(); it('should render self and subcomponents', () => { const wrapper = mount( <Provider store={mockStore}> <MemoryRouter> <Component {...props} /> </MemoryRouter> </Provider> ); // 通过find查找你的原始组件(替换成你组件的实际名称) expect(toJson(wrapper.find('MyComponent'))).toMatchSnapshot(); });
为什么你之前的方法没生效?
shallow渲染只会渲染组件的最外层,而你的默认导出是HOC返回的Route组件,所以看不到内部的原组件;.dive()没用是因为Route的render是一个函数,shallow无法解析这个函数返回的组件;- 导入
{ Component }失败是因为原组件没有做命名导出,只有默认导出是被HOC处理后的结果。
内容的提问来源于stack exchange,提问作者Esther Cuan
相关产品推荐
相关产品推荐

