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

如何使用React Testing Library模拟基于Hook实现的服务返回数据

问题修复方案

你目前的mock失败主要是核心实现不匹配导致的,按如下步骤修改即可:

1. 修正jest.mock的调用规则与返回结构

  • jest.mock 不能放在beforeEach内部,必须放在测试文件顶级作用域,jest的模块mock提升机制不支持块级调用
  • 你的usePanelClient调用后会返回一个函数,二次调用才会拿到接口方法集合,mock的结构要和原实现完全对齐
  • 原axios请求返回的是包含data字段的响应对象,mock的getPendingAwards返回值要符合该结构

2. 补充缺失的依赖mock

组件引入了useUtils自定义Hook,未mock会导致解构formatCurrency时报错,需要同步mock该依赖。

3. 异步逻辑需要等待完成

组件内的接口调用是异步操作,断言数据渲染前需要等待异步任务执行完毕,使用React Testing Library的waitFor工具即可。


修正后的完整测试代码

import React from 'react'
import { render, waitFor } from '@testing-library/react'
import { Router } from 'react-router-dom'
import { createMemoryHistory } from 'history'

import PendingAwards from './PendingAwards'

// 模块mock必须放在顶级作用域
jest.mock('../../../clients/PanelClient/usePanelClient', () => {
  return jest.fn(() => {
    // 对齐原Hook返回结构:usePanelClient()返回一个函数
    const mockData = {
      quantity: 820,
      amount: 26681086.12,
      commission: 5528957.841628,
    }
    return () => ({
      // 对齐axios返回结构:{data: 实际数据}
      getPendingAwards: jest.fn(() => Promise.resolve({ data: mockData })),
    })
  })
})

// 补充mock useUtils依赖
jest.mock('../../../hooks/useUtils', () => ({
  __esModule: true,
  default: () => ({
    formatCurrency: (val) => `R$ ${val.toFixed(2).replace('.', ',')}`
  })
}))

// 静态资源mock(如果你的测试环境已默认配置svg mock可以省略)
jest.mock('../../../assets/img/panel/ico-file.svg', () => 'mock-file-icon')
jest.mock('../../../assets/img/panel/ico-exclamation.svg', () => 'mock-exclamation-icon')
jest.mock('../../../assets/img/panel/awesome-pause-circle.svg', () => 'mock-pause-icon')

describe('PendingAwards Component', () => {
  it('组件正常挂载且正确渲染待奖励数据', async () => {
    const history = createMemoryHistory()
    const { getByText } = render(
      <Router history={history}>
        <PendingAwards />
      </Router>,
    )
    // 等待异步接口返回、数据渲染完成
    await waitFor(() => {
      expect(getByText('820')).toBeInTheDocument()
      expect(getByText('R$ 26681086,12')).toBeInTheDocument()
    })
  })

  it('地址栏包含scrollTo参数时触发滚动到顶部', () => {
    const history = createMemoryHistory()
    history.push({
      search: '?scrollTo=pendingAwards',
    })
    window.scrollTo = jest.fn()
    render(
      <Router history={history}>
        <PendingAwards />
      </Router>,
    )
    expect(window.scrollTo).toHaveBeenCalledWith({ behavior: 'smooth', top: 0 })
  })
})

额外注意点

如果仍有路由相关报错可以检查你的React Router版本,v6的Router组件用法和v5不同,替换为MemoryRouter组件即可直接使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 02:36:02