React Jest测试含onFocus的输入组件时出现警告问题求助
问题描述
我开发的React组件包含如下表单输入字段:
<Form.Label>E-mail</Form.Label> <Form.Control data-testid="inputemail" type="email" onFocus={() => setAttribute(false)} readOnly={attribute} placeholder="Enter e-mail" /> </Form.Group>
我编写了对应的Jest测试用例:
it("should change 'Email' input value", async () => { render(<LoginPage />); const textVariable = ""; const inputemail = screen.getByTestId("inputemail"); inputemail.focus(); fireEvent.input(inputemail, { target: { value: textVariable } }); expect(inputemail).toHaveFocus(); // 目前能通过 await waitFor(() => { expect(inputemail.innerHTML).toBe(textVariable); }); });
测试用例执行通过,但出现了警告,请问该如何解决?
解决方案
警告根源
- 只读状态未更新时触发输入事件:组件中
Form.Control的readOnly由attribute控制,只有在onFocus触发后才会调用setAttribute(false)解除只读。但测试中在focus()后立刻触发input事件,此时组件可能还没完成状态更新,对只读输入框触发输入操作会触发React警告。 - 错误的断言对象:输入框的值存储在
value属性中,而非innerHTML——innerHTML用于获取元素内部的HTML内容,用它断言输入值属于无效操作,且没必要用waitFor包裹这个断言。
修复步骤
- 等待只读状态解除:在
focus()后,用waitFor等待输入框的只读状态被移除,确保后续输入事件是合法的:await waitFor(() => { expect(inputemail).not.toHaveAttribute('readonly'); }); - 修正断言逻辑:将
expect(inputemail.innerHTML).toBe(textVariable)改为expect(inputemail.value).toBe(textVariable),且输入事件触发后value会同步更新,无需异步等待。 - 优化测试用例(可选):建议使用非空测试值,空值无法有效验证输入逻辑的正确性。优化后的完整测试代码如下:
it("should change 'Email' input value", async () => { render(<LoginPage />); const testEmail = "test@example.com"; const inputemail = screen.getByTestId("inputemail"); inputemail.focus(); // 等待只读状态解除 await waitFor(() => { expect(inputemail).not.toHaveAttribute('readonly'); }); fireEvent.input(inputemail, { target: { value: testEmail } }); expect(inputemail).toHaveFocus(); expect(inputemail.value).toBe(testEmail); });
额外建议
- 若需要验证
setAttribute是否被正确调用,可以用jest.spyOn监听状态更新函数,比如:const mockSetAttribute = jest.fn(); // 假设attribute是组件状态,通过props或mock传递 render(<LoginPage setAttribute={mockSetAttribute} />); // ...后续测试中可以断言mockSetAttribute被调用 expect(mockSetAttribute).toHaveBeenCalledWith(false);
内容的提问来源于stack exchange,提问作者rafa_pe
相关产品推荐
相关产品推荐

