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

使用React Router v6.4测试时出现ReferenceError: Request is not defined

解决React Router v6测试中ReferenceError: Request is not defined错误

问题背景

使用React Testing Library结合Vitest测试React Router v6的路由跳转逻辑时,采用RouterProvider+createMemoryRouter配置,点击路由链接后触发未处理拒绝错误:ReferenceError: Request is not defined,初始页面渲染正常,但跳转时失败。

错误原因

React Router v6.4+引入的loader/action机制依赖浏览器原生的Request API,但Vitest运行在Node.js环境中,该环境默认未全局提供Request对象,当路由跳转触发loader执行时,内部创建Request实例就会抛出此错误。

可行解决方案

1. 全局polyfill Request对象

React Router内部使用@remix-run/web-fetch实现fetch相关功能,我们可以直接用这个包来polyfill:

  • 安装依赖:
npm install -D @remix-run/web-fetch
  • 在测试文件顶部添加:
import { Request } from '@remix-run/web-fetch';
globalThis.Request = Request;

如果需要全局生效,可创建vitest.setup.ts文件:

import { Request } from '@remix-run/web-fetch';
globalThis.Request = Request;

然后在vite.config.ts的测试配置中指定:

export default defineConfig({
  test: {
    setupFiles: ['./vitest.setup.ts'],
    // 其他测试配置
  },
});

2. Mock路由loader(仅测试跳转逻辑时适用)

如果测试只需要验证路由跳转后的组件渲染,不需要测试loader的业务逻辑,可以mock掉loader:

const router = createMemoryRouter(
  routes.map(route => ({
    ...route,
    loader: route.loader ? () => Promise.resolve({}) : undefined,
  })),
  { initialEntries: ['/'] }
);

3. 使用React Router官方测试工具包

React Router提供了@remix-run/testing包,内置了测试所需的环境polyfill:

  • 安装依赖:
npm install -D @remix-run/testing
  • 替换createMemoryRouter为createTestRouter:
import { createTestRouter } from '@remix-run/testing';

const router = createTestRouter(routes, { initialEntries: ['/'] });

测试示例

修改配置后,重新编写测试验证跳转:

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { RouterProvider } from 'react-router-dom';
import { createMemoryRouter } from 'react-router-dom';
import { routes } from '../path-to-routes';
import { Request } from '@remix-run/web-fetch';

globalThis.Request = Request;

test('点击登录链接跳转到登录页', async () => {
  const router = createMemoryRouter(routes, { initialEntries: ['/'] });
  const user = userEvent.setup();

  render(<RouterProvider router={router} />);

  await user.click(screen.getByText('登录'));
  expect(screen.getByRole('form', { name: /登录/i })).toBeInTheDocument();
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 04:45:37