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

如何Mock调用API的函数?测试ErrorPage渲染遇TypeError问题求助

问题解决:Mock API调用时出现TypeError: callApiAndSendForm.mockRejectedValue is not a function

问题背景

我有一个带按钮的组件,点击按钮会触发函数并发起API调用,希望测试API调用失败时ErrorPage是否正确渲染,且不想直接mock组件内的setHasApiError。相关核心代码如下:

MainPage.tsx

export const MainPage: FC = () => {
  const [hasApiError, setHasApiError] = useState<boolean>(false)

  if (hasApiError) {
    return <ErrorPage data-testid="error-page" /> // 原代码缺少return,需补充才能正确渲染ErrorPage
  }

  return <PageWithForm submitHandler={submitHandler(setHasApiError)} />
}

PageWithForm/PageWithFormServices.tsx

import { callApiAndSendForm } from '../services/callApiAndSendForm'

export const submitHandler = 
  (setHasApiError: Dispatch<SetStateAction<boolean>>): SubmitHandler<FormData> => 
  async (data: FormData) => {
    try {
      const response = await callApiAndSendForm(data)
      // 其他逻辑...
    } catch(error) {
      setHasApiError(true)
    }
  }

services/callApiAndSendForm.ts

export const callApiAndSendForm = async (data: FormData): Promise<ResponsesFromApi> =>
  fetch('/api/...', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(data)
  }).then((res) => res.json())

尝试mockcallApiAndSendForm时出现错误:TypeError: callApiAndSendForm.mockRejectedValue is not a function,测试代码如下:

const callApiAndSendFormMock = callApiAndSendForm as jest.Mock

it('should render ErrorPage if api call fails', async () => {
  callApiAndSendFormMock.mockRejectedValue('error')
  const { getById } = renderMainPage()  
  expect(getById('error-page').toBeVisible())
})

错误原因

直接将原函数断言为jest.Mock并没有真正把它转换成Mock函数,Jest需要通过jest.mock来接管整个模块的导出,才能生成带有mock方法的函数实例。

解决步骤及完整测试代码

1. 正确mock服务模块

在测试文件顶部用jest.mockmockcallApiAndSendForm所在的模块:

import { callApiAndSendForm } from '../services/callApiAndSendForm'

// Mock整个callApiAndSendForm模块
jest.mock('../services/callApiAndSendForm', () => ({
  callApiAndSendForm: jest.fn()
}))

// 类型断言为jest.Mock,方便调用mock方法
const mockCallApiAndSendForm = callApiAndSendForm as jest.Mock

2. 完善测试用例

需要模拟点击提交按钮触发API调用,并等待状态更新后断言:

it('should render ErrorPage when API call fails', async () => {
  // 配置Mock函数抛出错误
  mockCallApiAndSendForm.mockRejectedValue(new Error('API Error'))

  // 渲染页面
  const { getByRole, queryByTestId } = render(<MainPage />)

  // 模拟点击提交按钮(假设按钮的role是"button",文本为"提交")
  fireEvent.click(getByRole('button', { name: /提交/i }))

  // 等待ErrorPage渲染并断言可见
  await waitFor(() => {
    expect(queryByTestId('error-page')).toBeVisible()
  })
})

额外注意点

  • 原MainPage中的if (hasApiError)分支缺少return,需补充return <ErrorPage/>才能在错误状态下正确渲染错误页,否则测试会失败。
  • 使用waitFor等待异步操作完成后的状态更新,因为API调用是异步的,状态更新和组件渲染需要时间。
  • 建议给ErrorPage添加data-testid属性,比用id更适合测试场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 07:15:55