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

Vitest环境下React+Redux-Toolkit应用useNavigate模拟失效求助

解决Vitest中Mock react-router-dom useNavigate时的BrowserRouter缺失问题

问题修复代码

你的报错根源是mock后的react-router-dom未导出BrowserRouter,而测试工具函数renderWithProviders依赖该组件。修改测试文件中的mock逻辑如下:

import React from 'react';
import { renderWithProviders } from '../../../../tests_setup/test-utils';
import { screen, fireEvent } from '@testing-library/dom';
import { useNavigate } from 'react-router-dom';
import SearchInput from '../SearchInput';
import { resetSearch, updateSearchterm, getData } from '../../../features/data/dataSlice';

const mockUseNavigate = vi.fn();

vi.mock('react-router-dom', async (importOriginal) => {
  // 导入原模块的所有导出
  const actual = await importOriginal();
  return {
    ...actual, // 保留原模块所有导出(包括BrowserRouter)
    // 覆盖useNavigate钩子,返回mock导航函数
    useNavigate: () => mockUseNavigate,
  };
});

测试时,触发组件中调用导航的逻辑后,可通过以下断言验证:

expect(mockUseNavigate).toHaveBeenCalledWith('/your-target-path');

原理讲解

  1. Vitest模块Mock机制
    使用vi.mock会完全替换目标模块的导出。若仅需部分mock(如仅修改useNavigate),必须通过importOriginal导入原模块的完整导出,再覆盖需要自定义的部分。否则原模块的其他导出(如BrowserRouter、Route等)会被清空,导致依赖这些导出的代码报错。

  2. useNavigate的Mock逻辑
    useNavigate是返回导航函数的React钩子,因此mock时需要让该钩子返回你定义的mockUseNavigate函数。这样组件内调用const navigate = useNavigate()时,navigate就是你的mock函数,可追踪其调用参数和次数。

  3. 为什么之前的实现失败?
    尽管你使用了importActual导入原模块,但在ES模块导出的处理上可能存在隐性问题,导致BrowserRouter未被正确继承。使用importOriginal(Vitest推荐的替代importActual的工具)能更稳定地处理模块导出。

额外优化建议

  • 将react-router-dom的通用mock逻辑抽离到测试工具文件中,避免重复编写。
  • 在beforeEach钩子中重置mock函数,避免测试用例间的状态污染:
    beforeEach(() => {
      mockUseNavigate.mockReset();
    });
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 03:27:20