带useSelector的React函数组件结合redux-mock-store做快照测试失败的写法咨询
当前测试代码的核心问题
- 导入导出不匹配:业务组件是默认导出
export default CardList,但测试代码使用了命名导入import { CardList } from './CardList',会导致导入的组件值为undefined,这就是快照中出现<UNDEFINED>异常节点的根本原因。 - Provider使用逻辑错误:Provider组件必须通过自身的
store属性传入Redux store实例,原代码把store作为prop直接传给CardList,既不符合Provider的使用规范,也和CardList使用useSelector的取值逻辑不匹配。 - 模拟Store结构不匹配业务取值路径:原代码直接把mockRobots数组作为mockStore的入参,但业务代码的useSelector需要从全局state中读取
state.requestRobots.robots、state.searchRobots.searchField、state.requestRobots.pending三个路径的内容,结构不匹配会直接触发取值报错。 - 渲染逻辑无效:原代码虽然引入了enzyme的shallow方法,但从未实际调用完成组件渲染;且shallow渲染仅会渲染当前组件的第一层结构,无法穿透Provider解析内部hook组件的真实内容,本身就不适合做带Redux上下文、带hook组件的快照测试。
修正后的可运行测试代码
目前React生态下,针对带hook的函数组件,使用@testing-library/react的渲染方法做快照测试兼容性更好,不需要额外配置enzyme对React 17+版本、hook的兼容补丁,能避免大部分渲染结构异常问题。
import React from 'react'; import { render } from '@testing-library/react'; import { Provider } from 'react-redux'; import configureStore from 'redux-mock-store'; // 修正导入方式,匹配业务组件的默认导出 import CardList from './CardList'; import '../../setUpTest'; // 按照业务代码的state取值路径构建模拟state结构 const mockState = { requestRobots: { robots: [ { id: 1, name: 'robocop', email: 'robocop@gmail.com', } ], pending: false, }, searchRobots: { searchField: 'rob' } }; // 初始化模拟Store工厂 const mockStore = configureStore(); it('expect to render CardList component', () => { // 传入模拟state生成可用的Store实例 const store = mockStore(mockState); // 渲染组件树:将Store绑定到Provider上,包裹CardList组件 const { asFragment } = render( <Provider store={store}> <CardList /> </Provider> ); // 对渲染生成的真实DOM片段做快照对比 expect(asFragment()).toMatchSnapshot(); });
关键修正说明
- 替换导入方式:匹配业务组件的默认导出规则,从根源上避免出现组件值为undefined的异常
- 重构模拟State结构:完全对齐useSelector中的取值路径,避免出现
Cannot read property of undefined的运行时报错 - 修正Provider配置:将Store实例绑定到Provider的
store属性上,让组件内部的useSelector可以正确读取到模拟的Redux状态 - 替换渲染方案:用
render方法生成完整的可解析组件树,生成的快照结构和实际页面渲染结果完全一致,不会出现之前的节点嵌套错乱、UNDEFINED节点问题 - 小提示:如果项目必须保留enzyme的使用,需要把
shallow替换为mount方法,否则shallow渲染无法穿透Provider的上下文层,依然无法获取到组件的真实渲染结构。另外业务代码中return的div标签内、map循环后多余的独立分号会被渲染为文本节点,可以同步删除这个多余的分号,让快照结构更干净。
内容的提问来源于stack exchange,提问作者user6248190
相关产品推荐
相关产品推荐

