如何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
相关产品推荐
相关产品推荐

