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

如何使用Vitest模拟RTK Query Hook?

解决Vitest模拟RTK Query Hook时返回undefined的问题

问题分析

你遇到的TypeError: Cannot destructure property 'data' of 'useGetFieldValueQuery(...)' as it is undefined错误,说明useGetFieldValueQuery被调用后返回了undefined。虽然你已经确认mock路径正确且能看到Mock called日志,但大概率是mock的导出结构与实际模块的导出方式不匹配,或者mock函数的返回值未被正确绑定。

解决方案

方案1:显式在测试用例中设置mock返回值

避免模块加载顺序导致的mock初始化问题,先在vi.mock中仅定义空的mock函数,再在测试用例里显式设置返回值:

import { vi } from "vitest"
import { ReactElement } from "react"
import { render, screen } from "@testing-library/react"
import { FormProvider, useForm } from "react-hook-form"
import SelectField from "./SelectField"
import { useGetFieldValueQuery } from "path/to/rtkQueryCreateApi"

// 仅初始化mock函数,不设置返回值
vi.mock("path/to/rtkQueryCreateApi", () => ({
  useGetFieldValueQuery: vi.fn(),
}))

const mockElement = {
  label: "Test Select Label",
  fieldName: "testField",
  componentType: "select", // 注意:原componentType为checkbox,与SelectField组件不匹配,改为select
  id: "test-select",
  width: 3,
}

type WrapperProps = {
  children: ReactElement
}

describe("SelectField Component", () => {
  it("renders options correctly from string filter", () => {
    // 在测试用例中显式设置mock的返回值
    useGetFieldValueQuery.mockReturnValue({
      data: {
        d: {
          results: [
            { id: "1", text: "Option 1" },
            { id: "2", text: "Option 2" },
          ],
        },
      },
      isLoading: false,
      isError: false,
      isSuccess: true,
      error: null,
      refetch: vi.fn(),
    })

    const Wrapper = ({ children }: WrapperProps) => {
      const methods = useForm()
      return <FormProvider {...methods}>{children}</FormProvider>
    }

    render(
      <Wrapper>
        <SelectField element={mockElement} errors={undefined} />
      </Wrapper>,
    )

    expect(screen.getByText("Option 1")).toBeInTheDocument()
    expect(screen.getByText("Option 2")).toBeInTheDocument()
  })
})

方案2:匹配实际模块的导出结构

如果你的RTK Query API是默认导出API对象(而非直接命名导出hook),比如实际模块代码如下:

// path/to/rtkQueryCreateApi.ts
const api = createApi({ /* 配置 */ })
export default api
export const { useGetFieldValueQuery } = api

那么需要调整mock的结构,确保默认导出的对象包含目标hook:

vi.mock("path/to/rtkQueryCreateApi", () => ({
  default: {
    useGetFieldValueQuery: vi.fn(() => ({
      data: {
        d: {
          results: [
            { id: "1", text: "Option 1" },
            { id: "2", text: "Option 2" },
          ],
        },
      },
      isLoading: false,
      isError: false,
      isSuccess: true,
      error: null,
      refetch: vi.fn(),
    })),
  },
  // 同时保留命名导出(如果组件是直接导入hook的话)
  useGetFieldValueQuery: vi.fn(() => ({ /* 同上返回值 */ })),
}))

额外注意点

你的mockElement中componentType设置为"checkbox",但组件是SelectField,这可能导致组件渲染复选框而非下拉选项,即使mock数据正确也无法找到预期文本,建议改为组件预期的类型(比如"select")。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 11:11:03