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

React单元测试报错:无法在<Router>内部渲染另一个<Router>

解决React单元测试中路由嵌套错误并测试路由参数

问题根源

你的App组件内部已经用BrowserRouter包裹了路由,测试时再套一层MemoryRouter就造成了路由嵌套,React Router不允许同时存在多个Router实例,所以抛出了错误。

解决方案

方法1:抽离Router到入口文件(推荐)

把BrowserRouter从App组件中移到项目入口文件(比如index.js),让App组件只负责路由配置(Routes/Route部分),这样测试时就能直接用MemoryRouter包裹App,不会产生嵌套。

修改代码:

  • index.js(入口文件):
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);
  • App.js:
import { Routes, Route } from 'react-router-dom';
import Home from './Home';
import List from './List';

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/list/:offset" element={<List />} />
    </Routes>
  );
}

export default App;

测试代码示例:

import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import App from './App';

test('测试带有offset参数的路由', () => {
  render(
    <MemoryRouter initialEntries={['/list/10']}>
      <App />
    </MemoryRouter>
  );
  
  // 验证组件是否正确接收offset参数并渲染
  expect(screen.getByText(/当前偏移量:10/i)).toBeInTheDocument();
});

方法2:不修改App结构,直接测试路由组件

如果不想调整App的结构,可以直接测试App内部的路由组件,跳过外层的BrowserRouter,或者用jest mock替换BrowserRouter。

示例:直接渲染路由组件

import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import List from './List';

test('测试offset参数', () => {
  render(
    <MemoryRouter initialEntries={['/list/20']}>
      <List />
    </MemoryRouter>
  );
  
  expect(screen.getByText(/偏移量:20/i)).toBeInTheDocument();
});

示例:用jest mock替换BrowserRouter

import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import App from './App';

// mock掉BrowserRouter,让它直接渲染子组件
jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  BrowserRouter: ({ children }) => children,
}));

test('测试App的路由参数', () => {
  render(
    <MemoryRouter initialEntries={['/list/15']}>
      <App />
    </MemoryRouter>
  );
  
  expect(screen.getByText(/当前offset:15/i)).toBeInTheDocument();
});

测试路由参数的核心技巧

用MemoryRouter的initialEntries属性设置测试的路由路径,比如initialEntries={['/list/10']},这样组件就能通过useParams()获取到offset参数,你只需要验证组件是否根据参数正确渲染内容即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 17:16:27