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

如何在TypeScript中用Jest mockImplementation模拟自定义Hook实现组件单元测试

React自定义Hook单元测试模拟方案

现有写法问题

你当前的jest.mock写法不符合Hook的调用逻辑:useAPICall本身是可执行的函数,你直接返回了包含onAPICall的对象,执行useAPICall(123)时会因为返回值不是可调用函数报错。

正确模拟方式

1. 全局基础模拟

首先在测试文件顶层编写全局模拟逻辑,完全替换原Hook的实现:

jest.mock('@src/hooks/useAPICall', () => {
  // 返回模拟的useAPICall函数,执行后返回Hook的模拟返回值
  return jest.fn(() => ({
    onAPICall: jest.fn()
  }))
})

该写法会完全屏蔽原Hook的所有逻辑,测试时不会执行原Hook的任何代码,符合你的需求。

2. 测试用例编写示例

以React Testing Library为例,完整测试代码如下:

import { render, screen, fireEvent } from '@testing-library/react'
import App from './App'
import useAPICall from '@src/hooks/useAPICall'

// 类型声明(TS环境可选,用于获取模拟函数的类型提示)
const mockUseAPICall = useAPICall as jest.Mock

describe('App组件测试', () => {
  // 每个用例执行前清空模拟函数的调用记录,避免用例间相互干扰
  beforeEach(() => {
    mockUseAPICall.mockClear()
  })

  it('点击按钮时触发onAPICall调用', () => {
    // 自定义本次Hook调用的返回值,方便后续断言
    const mockOnAPICall = jest.fn()
    mockUseAPICall.mockReturnValue({
      onAPICall: mockOnAPICall
    })

    render(<App />)
    // 触发按钮点击
    fireEvent.click(screen.getByRole('button', { name: /click/i }))
    
    // 断言逻辑
    expect(mockUseAPICall).toHaveBeenCalledWith(123) // 验证Hook传入参数正确
    expect(mockOnAPICall).toHaveBeenCalledTimes(1) // 验证接口调用方法被触发
  })
})

3. 无返回值Hook的模拟说明

如果你的自定义Hook没有返回值,只需要修改mockImplementation的返回逻辑即可:

// 模拟无返回值的自定义Hook
mockUseAPICall.mockImplementation(() => {
  // 不需要返回任何内容
  // 也可以在这里添加模拟的副作用逻辑
})

注意事项

  • jest.mock必须写在测试文件的顶层,不能放在测试用例内部,jest会自动提升该方法的执行优先级,早于所有import语句执行
  • 不同测试用例需要不同Hook返回值时,直接在对应用例内调用mockReturnValue/mockImplementation覆盖即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 14:48:03