React新手求助:编写使用useAuthContext的Jest测试时渲染报错
解决React中useAuthContext的Jest测试报错问题
问题说明
我不熟悉React,但需要编写使用useAuthContext的Jest单元测试,该Hook在同事开发的模块中被广泛使用。每次尝试渲染使用useAuthContext.js的组件时都会报错,错误提示为useAuthContext must be used inside an AuthContextProvider。我想了解如何传递该上下文,或是如何编写对应的渲染测试,尝试过多种方案但效果都不理想,恳请提供帮助!
相关代码
App.test.js
import React from "react"; import { render, screen } from "@testing-library/react"; import App from "./App"; import ReactDOM from 'react-dom'; import ShallowRenderer from 'react-shallow-renderer'; let realUseContext; let useContextMock; // Setup mock beforeEach(() => { realUseContext = React.useContext; useContextMock = React.useContext = jest.fn(); }); // Cleanup mock afterEach(() => { React.useContext = realUseContext; }); test("mock hook", () => { const element = new ShallowRenderer().render( <App /> ); }); test("render without failure", () => { const div = document.createElement("div"); ReactDOM.render(<App />, div); }); test("renders the nav bar", () => { render(<App />); const navbar = screen.getByTestId("navbar"); expect(navbar).toBeInTheDocument(); });
App.js
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom' import { useAuthContext } from './hooks/useAuthContext' // pages & components import Home from './pages/Home' import Login from './pages/Login' import Signup from './pages/Signup' import LostPassword from './pages/LostPassword' import WaitTimes from './pages/WaitTimes' import Navbar from './components/Navbar' function App() { const { user } = useAuthContext() return ( <div className="App"> <BrowserRouter> <Navbar /> <div className="pages"> <Routes> <Route path="/" element={user ? <Home /> : <Navigate to="/login" />} /> <Route path="/login" element={!user ? <Login /> : <Navigate to="/" />} /> <Route path="/signup" element={!user ? <Signup /> : <Navigate to="/" />} /> <Route path="/lost" element={!user ? <LostPassword /> : <Navigate to="/" />} /> <Route path="/wait" element={!user ? <WaitTimes /> : <Navigate to="/" />} /> </Routes> </div> </BrowserRouter> </div> ); } export default App;
useAuthContext.js
import { AuthContext } from "../context/AuthContext" import { useContext } from "react" export const useAuthContext = () => { const context = useContext(AuthContext) if(!context) { throw Error('useAuthContext must be used inside an AuthContextProvider') } return context }
解决方案
方法1:使用真实的AuthContextProvider包裹测试组件
直接在测试中导入项目中的AuthContextProvider,将被测试组件包裹起来,并传入模拟的上下文值:
// 导入AuthContextProvider(根据项目实际路径调整) import { AuthContextProvider } from './context/AuthContext'; test("renders the nav bar", () => { render( <AuthContextProvider value={{ user: null }}> {/* 可根据测试需求传入null或模拟用户对象 */} <App /> </AuthContextProvider> ); const navbar = screen.getByTestId("navbar"); expect(navbar).toBeInTheDocument(); });
这种方式最贴近真实运行环境,能覆盖不同用户状态下的路由跳转等场景。
方法2:Mock useAuthContext钩子
直接mock自定义的useAuthContext钩子,让它返回预设的上下文值:
// 在测试文件顶部mock钩子 jest.mock('./hooks/useAuthContext', () => ({ useAuthContext: () => ({ user: null, // 可根据测试场景改为{ id: '1', name: 'test' }等 }) })); test("renders the nav bar", () => { render(<App />); const navbar = screen.getByTestId("navbar"); expect(navbar).toBeInTheDocument(); }); // 测试用户已登录时的路由跳转 test("redirects to home when user is logged in", () => { jest.mock('./hooks/useAuthContext', () => ({ useAuthContext: () => ({ user: { id: '1' }, }) })); render(<App />); // 根据Home组件的特征元素验证跳转结果 expect(screen.getByText('Home')).toBeInTheDocument(); });
方法3:Mock React.useContext(适配现有代码思路)
如果你想沿用现有mock React.useContext的逻辑,需要让mock返回符合AuthContext要求的值,避免抛出错误:
import { AuthContext } from './context/AuthContext'; // 导入AuthContext beforeEach(() => { realUseContext = React.useContext; // 针对AuthContext返回模拟值,其他上下文调用保留原有逻辑 useContextMock = React.useContext = jest.fn((context) => { if (context === AuthContext) { return { user: null }; } return realUseContext(context); }); }); test("renders the nav bar", () => { render(<App />); const navbar = screen.getByTestId("navbar"); expect(navbar).toBeInTheDocument(); });
这种方式需要处理所有上下文调用场景,容易遗漏,因此更推荐前两种方案。
内容的提问来源于stack exchange,提问作者Zhe Wang
相关产品推荐
相关产品推荐

