如何在Jest中Mock React的useContext与useState?遇undefined问题求助
问题分析与解决建议
首先明确核心问题:你写的userActionMenuPopUpBuilder是普通函数,但直接在里面调用了React Hooks(useContext、useState),这违反了React Hooks的核心规则——Hooks只能在函数组件或自定义Hook(命名必须以use开头)的顶层执行。直接调用这类普通函数时,React的Hook运行环境没有被初始化,导致useContext无法正常工作,进而抛出undefined的错误。
步骤1:重构函数为合法的自定义Hook
把目标函数改成符合规范的自定义Hook,命名以use开头,这样才能合法使用React Hooks:
const MMycustomContext = React.createContext({}); // 重构为自定义Hook,命名遵循use开头的规范 export const useUserActionMenuPopUpBuilder = (action, target, id) => { const { statePath, breadcrumbers } = useContext(MMycustomContext); const [showPopUp, setShowPopUp] = useState(false); const [itemSelected, setItemSelected] = useState({}); // 必须返回一个真值(比如状态、方法的集合),否则测试的toBeTruthy会失败 return { showPopUp, setShowPopUp, itemSelected, setItemSelected }; };
步骤2:修正Jest测试逻辑
测试自定义Hook需要借助@testing-library/react-hooks提供的renderHook工具,它会模拟React的Hook运行环境。同时要确保mock的useContext返回值包含原函数中解构的属性(避免解构undefined报错):
- 先安装依赖:
npm install --save-dev @testing-library/react-hooks
- 编写测试代码:
import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; import { useUserActionMenuPopUpBuilder } from './你的文件路径'; describe('useUserActionMenuPopUpBuilder', () => { it('Should be Truthy', () => { // Mock useContext,返回原函数需要的statePath和breadcrumbers jest.spyOn(React, 'useContext').mockImplementationOnce(() => ({ statePath: '/mock-state-path', breadcrumbers: jest.fn() // 可以mock成空函数或具体实现 })); // 使用renderHook执行自定义Hook const { result } = renderHook(() => useUserActionMenuPopUpBuilder(mockAction, target, id)); expect(result.current).toBeTruthy(); }); });
额外注意点
- 原函数没有返回值,即使修复Hooks问题,测试的
toBeTruthy也会失败,所以必须让Hook返回一个真值对象或函数。 - 如果不想使用
react-hooks测试库,也可以把逻辑封装成一个小型组件,用@testing-library/react渲染组件后再断言,但自定义Hook的方式更贴合代码逻辑。 - 确保测试文件中正确导入了React,避免React模块未加载导致的
useContextundefined问题。
内容的提问来源于stack exchange,提问作者John doe
相关产品推荐
相关产品推荐

