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

React-router-dom按钮点击导航测试失败问题求助

问题描述

我用React Router实现了页面跳转功能,点击按钮可导航至/creation页面,组件代码如下:

export const Index = () => {
    return (
        <Box>
            <h1>Some title</h1>
            <Button component={Link} to={'/creation'}>Créer</Button>
        </Box>
    )
}

但编写测试用例验证导航行为时失败了,测试代码如下:

it("Should navigate to page 2 on button click", async() => {
        render(<Index />, {wrapper: BrowserRouter})
        const user = userEvent.setup()

        expect(screen.getByText(/Créer/i)).toBeInTheDocument() // 这一步正常

        await user.click(screen.getByText(/Créer/i))
        expect(screen.getByText(/Page 2/i)).toBeInTheDocument() // 这一步失败
    })

补充:该功能在生产环境可以正常使用,请问怎么解决测试失败的问题?

解决方案

测试失败的核心原因是:你只给Index组件套了BrowserRouter,但没有定义/creation路由对应的页面组件,React Router无法匹配路由并渲染目标页面。以下是几种解决方式:

1. 配置完整的路由规则

在测试中完整配置路由表,把Index和目标页面都注册到路由里,这样点击跳转后React Router能正确渲染目标页面:

import { Index } from './Index';
import { CreationPage } from './CreationPage'; // 导入你的目标页面组件
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

it("Should navigate to page 2 on button click", async() => {
  render(
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Index />} />
        <Route path="/creation" element={<CreationPage />} />
      </Routes>
    </BrowserRouter>
  );
  const user = userEvent.setup();

  expect(screen.getByText(/Créer/i)).toBeInTheDocument();

  await user.click(screen.getByText(/Créer/i));
  // 用waitFor等待异步渲染完成
  await waitFor(() => {
    expect(screen.getByText(/Page 2/i)).toBeInTheDocument();
  });
});

2. 用waitFor处理异步渲染

路由跳转和组件渲染是异步过程,直接断言可能会因为目标组件还没渲染好而失败,用waitFor包裹断言,确保等待元素出现后再验证。

3. 可选:改用MemoryRouter优化测试

MemoryRouter是React Router专为测试设计的组件,它在内存中管理路由状态,不依赖浏览器的history对象,测试更稳定:

import { MemoryRouter, Routes, Route } from 'react-router-dom';

// 替换BrowserRouter为MemoryRouter,initialEntries设置初始路由
render(
  <MemoryRouter initialEntries={['/']}>
    <Routes>
      <Route path="/" element={<Index />} />
      <Route path="/creation" element={<CreationPage />} />
    </Routes>
  </MemoryRouter>
);

4. 另一种思路:验证导航函数调用

如果不想渲染完整的目标页面,可以通过监听useNavigate的调用情况来验证导航行为,这种方式更轻量化:

import { useNavigate } from 'react-router-dom';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Index } from './Index';

// Mock useNavigate
jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useNavigate: jest.fn(),
}));

it("Should navigate to /creation when button is clicked", async() => {
  const mockNavigate = jest.fn();
  (useNavigate as jest.Mock).mockReturnValue(mockNavigate);

  render(<Index />, {wrapper: BrowserRouter});
  const user = userEvent.setup();

  await user.click(screen.getByText(/Créer/i));

  // 验证导航函数是否被调用,参数是否正确
  expect(mockNavigate).toHaveBeenCalledWith('/creation');
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 03:15:44