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

Vitest测试报错:如何验证useEffect中调用了asyncThunk

问题原因与解决方法

报错原因

你遇到的TypeError: [Function actionCreator] is not a spy or a call to a spy!错误,是因为fetchCoordinates是Redux Toolkit通过createAsyncThunk生成的action creator函数,并非Vitest的间谍(spy)函数。Vitest无法直接跟踪普通函数的调用次数,必须将目标函数转换为间谍函数后,才能使用toHaveBeenCalledTimes这类断言方法。

解决方案

下面提供两种可行的修改方案,任选其一即可:

方案一:使用vi.mock模块级Mock

直接Mock整个locationSlice模块,将fetchCoordinates替换为间谍函数:

import { describe, it, expect, beforeEach, vi } from 'vitest'
import { render } from '@testing-library/react'
import { Provider } from 'react-redux'

import App from '../App'
import store from '../app/store'
import * as locationSlice from '../features/location/locationSlice'

// Mock整个locationSlice模块,替换fetchCoordinates为间谍函数
vi.mock('../features/location/locationSlice', () => ({
  fetchCoordinates: vi.fn(),
}))

describe('App', () => {
  beforeEach(() => {
    // 每次测试前清空间谍函数的调用记录
    vi.clearAllMocks()
    render(
      <Provider store={store}>
        <App />
      </Provider>,
    )
  })

  it('组件挂载时调用fetchCoordinates', () => {
    expect(locationSlice.fetchCoordinates).toHaveBeenCalledTimes(1)
  })
})

方案二:使用vi.spyOn单独Spy目标函数

通过spyOn为fetchCoordinates创建间谍包装,测试完成后恢复原函数:

import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
import { render } from '@testing-library/react'
import { Provider } from 'react-redux'

import App from '../App'
import store from '../app/store'
import * as locationSlice from '../features/location/locationSlice'

describe('App', () => {
  let fetchCoordinatesSpy: vi.SpyInstance

  beforeEach(() => {
    // 为fetchCoordinates创建间谍函数,返回一个mock的action对象
    fetchCoordinatesSpy = vi.spyOn(locationSlice, 'fetchCoordinates').mockReturnValue({ type: 'mock-action-type' } as any)
    render(
      <Provider store={store}>
        <App />
      </Provider>,
    )
  })

  afterEach(() => {
    // 每次测试后恢复原函数,避免影响其他测试
    fetchCoordinatesSpy.mockRestore()
  })

  it('组件挂载时调用fetchCoordinates', () => {
    expect(fetchCoordinatesSpy).toHaveBeenCalledTimes(1)
  })
})

补充说明

两种方案的核心都是将fetchCoordinates转换为Vitest可跟踪的间谍函数,这样就能正常断言它的调用次数。如果你的测试还需要验证异步逻辑或dispatch的action,可以进一步扩展Mock的返回值,模拟成功/失败场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 20:45:33