如何用react-hook-form和vitest测试表单提交?提交测试失败排查
问题原因与修复方案
核心问题
- 错误的提交目标:你调用
fireEvent.submit的目标是按钮,但表单的submit事件需要触发在<form>元素上——直接触发按钮的submit不会正确触发useForm的handleSubmit逻辑。 - 未处理异步逻辑:
handleSubmit会将你的submitHandler包装为异步函数,且你的mock返回了Promise,测试中未等待异步操作完成就执行断言,导致断言时mock还未被调用。 - 冗余的提交操作:测试里连续调用两次submit,属于无效操作,反而可能干扰测试流程。
修复后的测试代码
const mockFunct = vi.fn((data: any) => { return Promise.resolve(data); }); it('Should submit the form ', async () => { const { getByPlaceholderText, getByTestId } = render( <Form submitHandler={mockFunct} /> ); const usernameInput = getByPlaceholderText('Username') as HTMLInputElement; const passwordInput = getByPlaceholderText('Password') as HTMLInputElement; const form = getByTestId('form') as HTMLFormElement; // 输入内容验证 fireEvent.change(usernameInput, { target: { value: 'Sam12_#' } }); fireEvent.change(passwordInput, { target: { value: 'pass' } }); expect(usernameInput.value).toBe('Sam12_#'); expect(passwordInput.value).toBe('pass'); // 触发表单提交,目标为form元素 fireEvent.submit(form); // 等待异步submitHandler执行完成后断言 await waitFor(() => { expect(mockFunct).toHaveBeenCalled(); // 可选:验证提交的参数是否正确 expect(mockFunct).toHaveBeenCalledWith({ username: 'Sam12_#', password: 'pass' }); }); });
额外优化建议
- 组件的
submitHandlerProps类型可更明确:当前为(data: any) => void,因mock返回Promise,建议修改为(data: {username: string; password: string}) => Promise<void>,避免类型不匹配。 - 若后续需要表单验证,可给yup schema添加必填规则(如
username: yup.string().required()),测试时可同步验证错误提示逻辑。
内容的提问来源于stack exchange,提问作者CinemaClub
相关产品推荐
相关产品推荐

