使用React Hook Form时表单测试未通过的原因是什么?
问题原因
@testing-library/user-event的交互方法(type、click等)全部是异步方法,返回Promise,不加await的话,测试代码会在交互操作还没执行完成时就提前运行断言,此时表单输入、提交触发都还没完成。react-hook-form提供的handleSubmit方法内部包含表单校验、数据序列化的异步逻辑,即便你传入的自定义onSubmit是同步函数,handleSubmit包裹后的实际触发时机也晚于同步断言的执行时机。
修复方案
修改测试代码,给所有异步交互加await,配合waitFor确保提交逻辑执行完成即可:
import { render, screen, waitFor } from "@testing-library/react"; import App from "./App"; import userEvent from "@testing-library/user-event"; test("email and password field are clear for submit", async () => { const mockSubmit = jest.fn(); render(<App onSubmit={mockSubmit} />); // 所有userEvent操作都加await等待执行完成 await userEvent.type(screen.getByPlaceholderText(/email/i), "test@example.com"); await userEvent.type(screen.getByPlaceholderText(/password/i), "password"); await userEvent.click(screen.getByText(/submit/i)); // 等待提交函数被调用,避免异步逻辑未执行完就断言 await waitFor(() => { expect(mockSubmit).toHaveBeenCalledTimes(1); }); // 可额外校验提交参数是否符合预期 expect(mockSubmit).toHaveBeenCalledWith({ email: "test@example.com", password: "password" }); });
如果你使用的是userEvent v14及以上版本,官方更推荐先初始化user实例再调用方法,稳定性更高:
import { render, screen } from "@testing-library/react"; import App from "./App"; import userEvent from "@testing-library/user-event"; test("email and password field are clear for submit", async () => { const user = userEvent.setup() // 初始化user实例 const mockSubmit = jest.fn(); render(<App onSubmit={mockSubmit} />); await user.type(screen.getByPlaceholderText(/email/i), "test@example.com"); await user.type(screen.getByPlaceholderText(/password/i), "password"); await user.click(screen.getByText(/submit/i)); expect(mockSubmit).toHaveBeenCalledTimes(1); });
内容的提问来源于stack exchange,提问作者Prateek
相关产品推荐
相关产品推荐

