如何用Vitest测试自定义Hook内部的saveNewCustomSize函数?
解决Vitest测试自定义Hook时断言updateStaticCustom调用失败的问题
以下是针对你遇到的问题的排查方向和解决方案:
1. 确认触发路径的有效性
首先要排查rerunCustomQuery是否真的能触发saveNewCustomSize:
- 检查Hook内部逻辑:
rerunCustomQuery执行时是否存在条件分支(比如状态判断、参数校验),导致saveNewCustomSize未被调用。比如有没有传入的参数不满足触发条件? - 如果
saveNewCustomSize依赖Hook内部的某些状态,要确保测试时这些状态处于正确的初始值(可以通过renderHook的initialProps预设状态,或者调用Hook返回的状态修改方法设置)。
2. 修正mock函数的设置与重置
确保updateStaticCustom的mock是正确的:
- 用
vi.fn()创建mock函数后,要保证Hook实际引用的是这个mock实例(比如Hook通过props或context接收该函数时,测试中必须注入这个mock)。 - 每次测试前调用
mockFn.mockClear()或vi.clearAllMocks(),清除之前测试的调用记录,避免干扰当前断言。
3. 调整断言的匹配方式
直接断言对象相等时,容易因为引用不一致导致失败,建议改用以下方式:
- 用
expect.deepEqual()做深度值匹配:expect(mockUpdateStaticCustom).toHaveBeenCalledWith(expect.deepEqual(expectedPayload)) - 用
expect.objectContaining()断言关键属性匹配(适合只关心部分字段的场景):expect(mockUpdateStaticCustom).toHaveBeenCalledWith(expect.objectContaining({ size: 'custom', value: 100 }))
4. 处理异步操作
如果saveNewCustomSize或updateStaticCustom是异步函数,必须等待异步操作完成后再断言:
- 调用
rerunCustomQuery后,使用waitFor包裹断言:await waitFor(() => { expect(mockUpdateStaticCustom).toHaveBeenCalledWith(expect.deepEqual(expectedPayload)) }) - 如果
rerunCustomQuery本身是异步函数,要记得用await调用。
测试代码示例
import { vi, expect, waitFor } from 'vitest'; import { renderHook } from '@testing-library/react'; import useRerunCustomQuery from './useRerunCustomQuery'; describe('useRerunCustomQuery', () => { it('triggers updateStaticCustom with correct payload', async () => { // 创建mock函数 const mockUpdateStaticCustom = vi.fn(); // 渲染Hook并注入mock const { result } = renderHook(() => useRerunCustomQuery({ updateStaticCustom: mockUpdateStaticCustom, // 传入Hook所需的其他初始参数 initialSize: 'default' })); // 调用rerunCustomQuery,传入触发saveNewCustomSize的必要参数 await result.current.rerunCustomQuery({ targetSize: 'custom' }); // 等待异步操作完成并断言 const expectedPayload = { size: 'custom', value: 200 }; await waitFor(() => { expect(mockUpdateStaticCustom).toHaveBeenCalledWith(expect.deepEqual(expectedPayload)); }); }); });
额外提醒:可以在Hook内部saveNewCustomSize执行时临时添加日志,确认它是否被调用以及构造的payload是否符合预期,帮助快速定位问题。
内容的提问来源于stack exchange,提问作者Muhammad Umer Nisar
相关产品推荐
相关产品推荐

