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

如何在Jest中Mock第三方库的自定义Hook?

正确Mock第三方库自定义Hook的Jest方案

你遇到的问题核心是Mock时机不对,以及Mock方式不符合Jest的模块加载机制,以下是解决方法:

关键问题分析

  1. 方式一的问题:jest.mock不能放在it测试用例内部。Jest的模块Mock会被提升到文件顶部优先执行,如果在测试用例里才声明Mock,组件早就已经导入并使用了原始的Hook,Mock自然不会生效。
  2. 方式二的问题:如果只是返回普通函数而非jest.fn(),不仅无法动态修改返回值,同样可能因为Mock时机晚于组件导入,导致使用原始Hook。

正确实现步骤

1. 顶层声明Mock(必做)

把jest.mock放在测试文件的最顶部(所有import和测试用例之前),确保组件在导入时就使用Mock后的模块:

// 顶层Mock,优先于所有模块执行
jest.mock('@third/prod-data-component', () => ({
  // 将Hook定义为jest mock函数,方便后续动态修改返回值
  useProductData: jest.fn()
}));

// 必须在Mock之后导入组件和相关依赖
import ProductRow from './ProductRow';
import { render, screen } from '@testing-library/react';
// 导入Mock后的Hook,用于设置返回值
import { useProductData } from '@third/prod-data-component';

2. 在测试用例中动态设置返回值

在每个测试用例里,通过mockReturnValue或mockReturnValueOnce设置Hook的返回值:

it('渲染正确的产品数据', () => {
  // 给Mock的Hook设置返回值
  useProductData.mockReturnValue('foo');
  
  render(<ProductRow />);
  
  // 断言数据是否正确渲染
  expect(screen.getByText('foo')).toBeInTheDocument();
});

it('处理产品数据为undefined的情况', () => {
  // 另一个测试用例可以设置不同的返回值
  useProductData.mockReturnValue(undefined);
  
  render(<ProductRow />);
  
  // 断言无数据时的渲染结果
  expect(screen.queryByText('foo')).not.toBeInTheDocument();
});

3. 保留库中其他导出的真实实现(可选)

如果需要保留第三方库中其他导出的真实功能,仅MockuseProductData,可以这样写:

jest.mock('@third/prod-data-component', () => {
  // 获取库的真实实现
  const actualLib = jest.requireActual('@third/prod-data-component');
  return {
    // 保留其他所有导出
    ...actualLib,
    // 仅Mock目标Hook
    useProductData: jest.fn()
  };
});

注意事项

  • 必须确保组件的import语句在jest.mock之后,ES模块的静态导入会优先执行,提前导入组件会导致使用原始模块。
  • 每次测试用例执行后,可以用useProductData.mockClear()清除Mock的调用记录,避免测试用例之间的污染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 09:40:42