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

如何在Vitest中为每个测试动态设置自定义Hook的模拟返回值?

解决Vitest中自定义Hook单测试用例不同返回值的问题

问题根源

你当前的测试代码在beforeEach中提前渲染了组件,而每个测试用例里设置mock返回值的操作是在组件渲染之后执行的。这导致组件调用useGetStatusPageContent时,mock还未被设置返回值,自然返回undefined。

解决方案

调整测试流程:先设置mock返回值,再渲染组件。同时在beforeEach中重置mock,确保每个测试用例的环境干净无残留。

修改后的代码如下:

import { cleanup, render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, test, vi } from 'vitest'

import { useGetStatusPageContent } from '../../src/hooks/useGetStatusPageContent'
import KycStatusPage from '../../src/pages/KycStatusPage'
import { kycTestIds } from '../../testIds'
import { AppTestWrapper } from '../components/TestWrappers'

vi.mock('@inet-client-management-fe/shared', async (importOriginal) => {
  const actual = (await importOriginal()) as NonNullable<unknown>
  return {
    ...actual,
    useLoadingScreenContext: () => {
      return { loadingScreenExpired: false }
    }
  }
})

const mocks = vi.hoisted(() => {
  return {
    useGetStatusPageContent: vi.fn()
  }
})

vi.mock('../../src/hooks/useGetStatusPageContent', () => {
  return {
    useGetStatusPageContent: mocks.useGetStatusPageContent
  }
})

describe('KycStatusPage', () => {
  beforeEach(() => {
    // 重置mock,清除之前的调用记录和返回值,保证每个测试用例环境干净
    mocks.useGetStatusPageContent.mockReset()
  })
  afterEach(cleanup)

  test('Should display SplashActiveAlert', () => {
    // 1. 先设置当前测试需要的mock返回值
    mocks.useGetStatusPageContent.mockReturnValue({
      header: 'STATUS.PROCESSING_HEADER',
      message: 'STATUS.PROCESSING_MESSAGE',
      icon: 'info'
    })
    // 2. 再渲染组件,此时组件会使用已设置的mock数据
    render(
      <AppTestWrapper>
        <KycStatusPage />
      </AppTestWrapper>
    )
    expect(screen.getByTestId(kycTestIds.SplashActiveAlert)).toBeInTheDocument()
  })

  test('Should not display SplashActiveAlert', () => {
    // 1. 先设置当前测试需要的mock返回值
    mocks.useGetStatusPageContent.mockReturnValue({
      header: 'STATUS.CANT_PROCESS_HEADER',
      message: 'STATUS.CANT_PROCESS_MESSAGE',
      icon: 'bank'
    })
    // 2. 再渲染组件
    render(
      <AppTestWrapper>
        <KycStatusPage />
      </AppTestWrapper>
    )
    expect(screen.queryByTestId(kycTestIds.SplashActiveAlert)).not.toBeInTheDocument()
  })
})

关键调整点

  • 移除beforeEach中的render调用,避免组件提前渲染
  • 添加mockReset()到beforeEach,清除mock的历史状态,防止测试用例间互相干扰
  • 每个测试用例严格遵循「设置mock → 渲染组件 → 断言」的顺序
  • 直接使用mocks.useGetStatusPageContent操作mock,无需额外用vi.mocked()包装

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 20:05:22