Jest Dom匹配器toBeEnabled与not.toBeDisabled行为异常咨询
问题原因及解决方法
你的测试出现这种矛盾结果,核心原因是Formik的表单验证与状态更新是异步过程,你在触发字段操作后立刻断言,此时DOM可能还没完成状态同步,导致断言捕获到的是按钮的旧状态(enabled),所以toBeEnabled()会通过;而测试运行时的时序差异又可能让toBeDisabled()偶尔通过,属于不稳定的测试表现。
具体解决步骤:
- 用
waitFor等待异步状态更新
Formik在字段失焦后触发的验证是异步的,必须等待验证完成、DOM更新后再做断言。把断言逻辑包裹在waitFor中并使用await等待:
test("Submit is disabled when user enters invalid values", async () => { const handleSubmit = jest.fn(); render(<Reservations onSubmit={handleSubmit} />); // ... 字段操作代码 ... const submitButton = screen.getByRole("button", { name: /Submit/i }); // 等待按钮状态更新后断言 await waitFor(() => { expect(submitButton).toBeDisabled(); }); });
- 替换
fireEvent为userEvent
RTL官方更推荐使用@testing-library/user-event,它模拟真实用户的操作流程(比如输入时自动触发focus、change、blur),能更可靠地触发Formik的状态更新,同时简化代码:
首先安装依赖:
npm install --save-dev @testing-library/user-event@latest
修改测试代码:
import userEvent from '@testing-library/user-event'; test("Submit is disabled when user enters invalid values", async () => { const user = userEvent.setup(); const handleSubmit = jest.fn(); render(<Reservations onSubmit={handleSubmit} />); const firstNameField = screen.getByLabelText(/First Name/i); await user.type(firstNameField, "S"); // 自动触发focus、change、blur const lastNameField = screen.getByLabelText(/Last Name/i); await user.type(lastNameField, "S"); const emailField = screen.getByLabelText(/Email/i); await user.type(emailField, "S@s"); const dateField = screen.getByLabelText(/Choose date/i); await user.type(dateField, "2024-12-12"); const occasionField = screen.getByLabelText(/Occasion/i); await user.selectOptions(occasionField, "default"); const guestField = screen.getByLabelText(/Number of guests/i); await user.clear(guestField); await user.type(guestField, "-1"); const submitButton = screen.getByRole("button", { name: /Submit/i }); await waitFor(() => { expect(submitButton).toBeDisabled(); }); });
- 检查Formik按钮的
disabled绑定
确保你的提交按钮正确绑定了Formik的表单状态,比如:
<button type="submit" disabled={!formik.isValid || formik.isSubmitting} > Submit </button>
如果只绑定了isSubmitting,即使表单无效,按钮也会保持启用状态,这会直接导致你的断言不符合预期。
内容的提问来源于stack exchange,提问作者Sugirthan
相关产品推荐
相关产品推荐

