使用React Testing Library时App Router未挂载错误的解决求助
问题背景
开发环境中NavBar组件功能正常,但使用React Testing Library编写测试用例时,抛出invariant expected app router to be mounted错误,无法完成“点击登录按钮显示弹窗”的测试验证。
错误原因
NavBar和LoginCard组件依赖Next.js App Router的useRouter钩子,测试环境未初始化App Router上下文导致钩子调用失败;同时测试代码存在逻辑缺陷,未正确处理组件依赖的props和关联组件的渲染逻辑。
修复方案
1. 模拟useRouter钩子
在测试文件顶部添加jest.mock,模拟useRouter的实现,避免依赖真实路由环境:
jest.mock('next/navigation', () => ({ useRouter: () => ({ push: jest.fn(), }), }));
2. 提供必要props并关联组件状态
NavBar需要setVisibleLogin props才会渲染登录按钮,LoginCard依赖visibleLogin状态控制显示。测试时需创建共享状态,同时渲染两个关联组件:
import { render, screen } from "@testing-library/react" import userEvent from "@testing-library/user-event" import NavBar from "@/components/NavBar"; import LoginCard from "@/components/LoginCard"; import { useState } from 'react'; // 模拟Next.js路由钩子 jest.mock('next/navigation', () => ({ useRouter: () => ({ push: jest.fn(), }), })); describe("<NavBar>", () => { it ("点击登录按钮后显示登录弹窗", async () => { // 封装共享状态的测试容器 const TestWrapper = () => { const [visibleLogin, setVisibleLogin] = useState(false); return ( <> <NavBar setVisibleLogin={setVisibleLogin} /> <LoginCard visibleLogin={visibleLogin} setVisibleLogin={setVisibleLogin} data-testid="loginCard" /> </> ); }; render(<TestWrapper />); // 获取登录按钮(匹配文本忽略大小写) const loginButton = screen.getByRole("button", { name: /login\/sign up/i }); // 初始状态下弹窗不可见,用queryByTestId避免元素不存在报错 let loginCard = screen.queryByTestId("loginCard"); expect(loginCard).not.toBeVisible(); await userEvent.click(loginButton); // 点击后重新获取弹窗元素,验证可见性 loginCard = screen.getByTestId("loginCard"); expect(loginCard).toBeVisible(); }) });
3. 修正测试断言逻辑
- 删除错误断言
expect(loginButton).toBeCalled():按钮是DOM元素而非函数,该断言无效。 - 初始状态用
queryByTestId替代getByTestId:避免因元素不存在直接抛出测试错误。 - 点击按钮后重新获取弹窗元素:确保拿到状态更新后的最新DOM节点。
4. 可选:优化组件测试友好性
修改LoginCard的显示控制逻辑,用Tailwind的hidden类替代inline style,更便于测试断言:
// 替换LoginCard外层div的className和style <div className={`fixed left-1/2 top-1/2 -translate-x-2/4 -translate-y-2/4 z-50 ${visibleLogin ? '' : 'hidden'}`} data-testid="loginCard" >
内容的提问来源于stack exchange,提问作者Howard Cui
相关产品推荐
相关产品推荐

