You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用React Testing Library时App Router未挂载错误的解决求助

修复React Testing Library测试Next.js NavBar组件时的“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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 17:44:53