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

使用Vitest测试React组件时,react-router-dom Mock缺失BrowserRouter报错

解决Vitest测试React组件时react-router-dom模拟错误的问题

我在使用Vitest测试React组件(依赖MSW进行服务端模拟)时,遇到了如下错误:

Error: [vitest] No "BrowserRouter" export is defined on the "/node_modules/react-router-dom/dist/main.js" mock. Did you forget to return it from "vi.mock"?

测试中渲染组件的函数使用Router包裹目标组件,测试代码里尝试通过vi.mock覆盖useParams传入固定articleId,但无论是完全mock模块还是通过importOriginal保留原模块并覆盖useParams,都会触发上述错误。


方案1:使用vi.spyOn单独mockuseParams函数

无需mock整个react-router-dom模块,只针对useParams做局部mock,这样不会影响模块中其他组件(如BrowserRouter/MemoryRouter)的正常导入:

import * as reactRouterDom from 'react-router-dom';

describe('EntryDetail component', () => {
  beforeAll(() => server.listen());
  afterEach(() => {
    server.resetHandlers();
    vi.clearAllMocks(); // 清空mock,避免用例间数据污染
  });
  afterAll(() => server.close());

  it('allows only 150 characters for comments', async () => {
    // 单独mock useParams返回固定的articleId
    vi.spyOn(reactRouterDom, 'useParams').mockReturnValue({
      articleId: '63d466ca3d00b50db15aed93',
    });
    
    authorizedServerSetup();
    renderComponent();
    
    // 后续测试逻辑
    const commentInput = await screen.findByRole('textbox');
    // 验证字符限制的测试代码...
  });
});

方案2:正确mock整个模块并保留所有原导出

如果必须mock整个模块,需确保返回对象包含原模块的所有导出,包括测试用到的路由组件:

vi.mock('react-router-dom', async (importOriginal) => {
  const originalModule = await importOriginal();
  return {
    // 保留原模块所有命名导出
    ...originalModule,
    // 覆盖useParams
    useParams: vi.fn(() => ({
      articleId: '63d466ca3d00b50db15aed93',
    })),
    // 若使用了默认导出的路由组件,需额外保留
    default: originalModule.default,
  };
});

验证要点

  • 确认渲染组件时使用的Router(如BrowserRouter或MemoryRouter)是从react-router-dom正常导入的,未被错误覆盖。
  • 若使用MemoryRouter,直接在测试渲染函数中替换BrowserRouter即可,无需额外调整mock逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 09:25:42