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

使用Jest和Enzyme测试AppRouter时404页面未正常渲染问题排查

解决Jest+Enzyme测试AppRouter路由匹配404页面失败问题

你的测试失败的核心原因是AppRouter组件内部已经包含了<BrowserRouter>,而测试时又用<MemoryRouter>包裹,导致路由嵌套,外部MemoryRouter的initialEntries配置被内部的Router忽略。

每个Router组件(不管是BrowserRouter还是MemoryRouter)都会创建自己独立的路由上下文和history对象。当你嵌套两个Router时,内部的<BrowserRouter>会覆盖外部<MemoryRouter>的路由上下文,所以你设置的/random路径根本没有生效,路由依然匹配到了默认的Home页面,导致测试断言失败。

解决方案1:拆分Router与路由配置(推荐)

让AppRouter只负责定义路由规则(Switch和Route),把Router的职责移到应用入口,这样测试时可以自由用MemoryRouter包裹:

修改AppRouter组件:

import React from 'react';
import { Route, Switch } from 'react-router-dom';
import Home from './Home';
import NotFoundPage from './NotFoundPage';

// 只保留路由匹配逻辑,不再包含Router
const AppRouter = () => (
  <div>
    <Switch>
      <Route exact path="/" component={Home} />
      <Route component={NotFoundPage} />
    </Switch>
  </div>
);

export default AppRouter;

在应用入口文件(比如index.js)中添加Router:

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import AppRouter from './components/AppRouter';

ReactDOM.render(
  <Router>
    <AppRouter />
  </Router>,
  document.getElementById('root')
);

保持测试代码不变即可:

import React from 'react';
import { mount } from 'enzyme';
import { MemoryRouter } from 'react-router';
import AppRouter from './../src/components/AppRouter';
import Home from './../src/components/Home';
import NotFoundPage from './../src/components/NotFoundPage';

describe('App Router', () => {
  it('should go to 404 page', () => {
    const wrapper = mount(
      <MemoryRouter initialEntries={['/random']}>
        <AppRouter />
      </MemoryRouter>
    );
    expect(wrapper.contains(<Home />)).toBe(false);
    expect(wrapper.contains(<NotFoundPage />)).toBe(true);
  });
});

解决方案2:让AppRouter接受自定义history

如果你不想拆分组件,可以修改AppRouter,让它支持传入自定义的history对象,这样测试时可以传入MemoryHistory:

修改AppRouter组件:

import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Home from './Home';
import NotFoundPage from './NotFoundPage';

// 接受history属性,优先使用传入的history
const AppRouter = ({ history }) => (
  <Router history={history}>
    <div>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route component={NotFoundPage} />
      </Switch>
    </div>
  </Router>
);

export default AppRouter;

修改测试代码:

import React from 'react';
import { mount } from 'enzyme';
import { createMemoryHistory } from 'history';
import AppRouter from './../src/components/AppRouter';
import Home from './../src/components/Home';
import NotFoundPage from './../src/components/NotFoundPage';

describe('App Router', () => {
  it('should go to 404 page', () => {
    // 创建自定义MemoryHistory,指定初始路径
    const history = createMemoryHistory({ initialEntries: ['/random'] });
    const wrapper = mount(<AppRouter history={history} />);
    
    expect(wrapper.contains(<Home />)).toBe(false);
    expect(wrapper.contains(<NotFoundPage />)).toBe(true);
  });
});

两种方案都能解决你的问题,第一种更符合组件单一职责原则,后续扩展路由也更灵活。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:28:59