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

使用React Router v6的组件Jest快照测试运行失败求助

React Router v6 + Jest快照测试崩溃问题解决

问题场景

使用Jest运行快照测试时,所有用到react-router-dom组件(比如Link)的组件均崩溃,无法生成快照。

相关代码

header.tsx

import React from 'react';
import logo from '../../logo.svg'
import 'antd/dist/antd.min.css';
import { Link } from "react-router-dom";
import { PageHeader, Menu, Avatar, Button, Dropdown, Typography } from 'antd';
import { BellOutlined, UserOutlined } from '@ant-design/icons';

const { Title } = Typography;

const profileMenu = (
    <Menu
        items={[]}
    />
);

function WebHeader() {
    return (
        <PageHeader
            ghost={false}
            avatar={{
                src: <img src={logo} alt='icon' />,
                size: 48
            }}
            title={<Title level={1} style={{ marginBottom: 0 }}>SciOps</Title>}
            subTitle={
                <Menu mode="horizontal" defaultSelectedKeys={['projects']}>
                    <Menu.Item key="projects">
                        <Link to='/projects'>Projects</Link>
                    </Menu.Item>
                    <Menu.Item key="orgs">
                        <Link to='/organizations'>Organizations</Link>
                    </Menu.Item>
                </Menu>
            }
            extra={
                <>
                    <Button shape='circle' icon={<BellOutlined />} />
                    <Dropdown overlay={profileMenu} placement="bottom" arrow={{ pointAtCenter: true }} trigger={['click']}>
                        <a href="/#" onClick={e => e.preventDefault()}>
                            <Avatar size={36} icon={<UserOutlined />} style={{ marginRight: 0 }} />
                        </a>
                    </Dropdown>
                </>
            }
        ></PageHeader>
    )
}

export default WebHeader

header.test.tsx(原测试代码)

import React from 'react';
import renderer from 'react-test-renderer'
import WebHeader from '../../components/header/header'

it("Snapshot of Header", () => {
  const tree = renderer.create(<WebHeader />).toJSON();
  expect(tree).toMatchSnapshot();
})

错误信息(翻译后)

src/_test_/components/header.test.tsx
  ● 控制台输出

    console.error
      上述错误发生在<Link>组件中:
          at LinkWithRef (/home/adib/forks/sciops-hub/packages/react-router-dom/index.tsx:264:7)
          at span
          at li
          at DomWrapper (/home/adib/forks/sciops-hub/front-end/node_modules/rc-resize-observer/lib/SingleObserver/DomWrapper.js:31:34)
          at SingleObserver (/home/adib/forks/sciops-hub/front-end/node_modules/rc-resize-observer/lib/SingleObserver/index.js:27:24)
          at ResizeObserver (/home/adib/forks/sciops-hub/front-end/node_modules/rc-resize-observer/lib/index.js:27:24)
          at InternalItem (/home/adib/forks/sciops-hub/front-end/node_modules/rc-overflow/lib/Item.js:29:25)
          at InternalRawItem (/home/adib/forks/sciops-hub/front-end/node_modules/rc-overflow/lib/RawItem.js:29:23)
          at LegacyMenuItem (/home/adib/forks/sciops-hub/front-end/node_modules/rc-menu/lib/MenuItem.js:71:34)
          at InternalMenuItem (/home/adib/forks/sciops-hub/front-end/node_modules/rc-menu/lib/MenuItem.js:102:21)
          at MenuItem (/home/adib/forks/sciops-hub/front-end/node_modules/rc-menu/lib/MenuItem.js:232:24)
          at Trigger (/home/adib/forks/sciops-hub/front-end/node_modules/rc-trigger/lib/index.js:80:36)
          at Tooltip (/home/adib/forks/sciops-hub/front-end/node_modules/rc-tooltip/lib/Tooltip.js:29:32)
          at /home/adib/forks/sciops-hub/front-end/node_modules/antd/lib/tooltip/index.js:103:33)
          at MenuItem (/home/adib/forks/sciops-hub/front-end/node_modules/antd/lib/menu/MenuItem.js:61:37)
          at InheritableContextProvider (/home/adib/forks/sciops-hub/front-end/node_modules/rc-menu/lib/context/MenuContext.js:40:23)
          at ul
          at DomWrapper (/home/adib/forks/sciops-hub/front-end/node_modules/rc-resize-observer/lib/SingleObserver/DomWrapper.js:31:34)
          at SingleObserver (/home/adib/forks/sciops-hub/front-end/node_modules/rc-resize-observer/lib/SingleObserver/index.js:27:24)
          at ResizeObserver (/home/adib/forks/sciops-hub/front-end/node_modules/rc-resize-observer/lib/index.js:27:24)
          at Overflow (/home/adib/forks/sciops-hub/front-end/node_modules/rc-overflow/lib/Overflow.js:45:32)
          at InheritableContextProvider (/home/adib/forks/sciops-hub/front-end/node_modules/rc-menu/lib/context/MenuContext.js:40:23)
          at /home/adib/forks/sciops-hub/front-end/node_modules/rc-menu/lib/Menu.js:79:32)
          at /home/adib/forks/sciops-hub/front-end/node_modules/antd/lib/menu/index.js:72:24)
          at Menu (/home/adib/forks/sciops-hub/front-end/node_modules/antd/lib/menu/index.js:191:37)
          at span
          at div
          at div
          at div
          at DomWrapper (/home/adib/forks/sciops-hub/front-end/node_modules/rc-resize-observer/lib/SingleObserver/DomWrapper.js:31:34)
          at SingleObserver (/home/adib/forks/sciops-hub/front-end/node_modules/rc-resize-observer/lib/SingleObserver/index.js:27:24)
          at ResizeObserver (/home/adib/forks/sciops-hub/front-end/node_modules/rc-resize-observer/lib/index.js:27:24)
          at PageHeader (/home/adib/forks/sciops-hub/front-end/node_modules/antd/lib/page-header/index.js:129:45)
          at WebHeader
      考虑在组件树中添加错误边界来自定义错误处理行为。

      at logCapturedError (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8661:23)
      at update.callback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8694:5)
      at callCallback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:4092:12)
      at commitUpdateQueue (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:4113:9)
      at commitLayoutEffectOnFiber (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13232:13)
      at commitLayoutMountEffects_complete (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14330:9)
      at commitLayoutEffects_begin (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14316:7)
      at commitLayoutEffects (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14301:3)

问题原因

React Router的Link组件依赖Router提供的上下文(Context)才能正常工作,直接在测试中渲染包含Link的组件时,没有任何Router组件提供上下文,导致Link抛出错误。

解决方案

方案1:用MemoryRouter包裹组件

在测试中导入React Router的MemoryRouter,将WebHeader组件包裹在其中,提供路由上下文:

import React from 'react';
import renderer from 'react-test-renderer'
import { MemoryRouter } from 'react-router-dom'; // 导入MemoryRouter
import WebHeader from '../../components/header/header'

it("Snapshot of Header", () => {
  const tree = renderer.create(
    <MemoryRouter> {/* 包裹组件 */}
      <WebHeader />
    </MemoryRouter>
  ).toJSON();
  expect(tree).toMatchSnapshot();
})

方案2:Mock Link组件

如果不需要测试Link的路由功能,可以直接Mock react-router-dom的Link组件,让它渲染成普通的HTML标签(比如a标签或span):

import React from 'react';
import renderer from 'react-test-renderer'
import WebHeader from '../../components/header/header'

// Mock Link组件
jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  Link: ({ children, to }) => <a href={to}>{children}</a>,
}));

it("Snapshot of Header", () => {
  const tree = renderer.create(<WebHeader />).toJSON();
  expect(tree).toMatchSnapshot();
})

两种方案都能解决测试崩溃的问题,方案1更贴近真实环境,方案2则简化测试,专注于组件UI结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 18:16:06