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

NextJS导航栏测试:userEvent.click不触发路径更新的解决方法

解决Next.js中Jest测试Link组件路径不更新的问题

问题核心

你的测试代码存在两个关键问题:

  1. 手动创建的createMemoryHistory实例未与Next.js路由系统绑定,<Link>组件默认使用Next.js自身的路由机制,不会识别独立的history对象。
  2. 渲染<Navbar>时未包裹Next.js的路由上下文,导致点击Link后无法触发路由状态更新。

解决方案(分Next.js版本)

针对Next.js 12及以下(Pages Router)

使用next-router-mock模拟Next.js路由,确保测试能捕获路由变化:

  1. 安装依赖
npm install --save-dev next-router-mock
  1. 修改测试代码
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom/extend-expect';
import { useRouter } from 'next/router';
import Navbar from './Navbar';
import mockRouter from 'next-router-mock';

// 模拟next/router的useRouter钩子
jest.mock('next/router', () => ({
  useRouter: () => mockRouter,
}));

describe('Navbar Component', () => {
  beforeEach(() => {
    // 每次测试前重置路由到根路径
    mockRouter.push('/');
    render(<Navbar />);
  });

  it('navigates to /drones when clicking the drones link', async () => {
    const user = userEvent.setup();
    await user.click(screen.getByText('drones'));

    expect(mockRouter.pathname).toBe('/drones');
    expect(mockRouter.asPath).toBe('/drones');
  });

  it('navigates to /cameras when clicking the cameras link', async () => {
    const user = userEvent.setup();
    await user.click(screen.getByText('cameras'));

    expect(mockRouter.asPath).toBe('/cameras');
  });
});

针对Next.js 13+(App Router)

使用Next.js官方的MemoryRouter包裹组件,结合usePathname捕获当前路径:

  1. 确保依赖已安装(create-next-app生成的项目默认已包含)
npm install --save-dev @testing-library/react @testing-library/user-event jest
  1. 修改测试代码
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom/extend-expect';
import { MemoryRouter, usePathname } from 'next/navigation';
import Navbar from './Navbar';

// 辅助组件用于暴露当前路径
const CurrentPath = () => {
  const pathname = usePathname();
  return <span data-testid="current-path">{pathname}</span>;
};

describe('Navbar Component', () => {
  it('updates pathname to /drones when clicking drones link', async () => {
    render(
      <MemoryRouter initialEntries={['/']}>
        <Navbar />
        <CurrentPath />
      </MemoryRouter>
    );

    const user = userEvent.setup();
    await user.click(screen.getByText('drones'));

    expect(screen.getByTestId('current-path')).toHaveTextContent('/drones');
  });
});

额外注意事项

  • 若使用TypeScript,需安装对应类型依赖,比如@types/next-router-mock(针对Pages Router方案)。
  • 不要直接操作window.location,Next.js客户端路由不会直接修改该对象(除非配置强制刷新)。
  • 确保jest.config.js使用Next.js预设(create-next-app生成的项目默认配置了next/jest)。

内容的提问来源于stack exchange,提问作者Tolgahan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 10:45:02