You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Testing Library中禁用输入框仍可赋值的测试问题

为什么禁用的输入框在使用fireEvent.input时仍会被赋值?

我用React、Vitest和Testing Library写了如下测试代码:

import { describe, expect, it } from 'vitest';
import { fireEvent, render, screen } from '@testing-library/react';

describe('App button Problem', () => {
  it('types in the input correctly', async () => {
      render(<input type={'text'} disabled={false}/> );
      const input : HTMLInputElement = screen.getByRole('textbox');
      fireEvent.input(input, { target: { value: 'test' } });
      expect( input.value).toBe('test'); // 此断言正常通过
  });
  it('does not types in the input if disabled', async () => {
      render(<input type={'text'} disabled={true}/> );
      const input : HTMLInputElement = screen.getByRole('textbox');
      fireEvent.input(input, { target: { value: 'test' } });
      expect( input.value).toBe(''); // 此断言失败
  }); 
});

运行测试后得到错误:

AssertionError: expected 'test' to be '' // Object.is equality
Expected :
Actual   :test

问题原因

fireEvent是直接模拟DOM事件触发的工具,它不会像真实用户交互那样遵守输入框的disabled状态限制。在真实浏览器中,禁用的输入框不会响应输入事件,也不会更新值,但fireEvent会强制触发input事件并直接设置元素的value属性,所以即便输入框处于禁用状态,值还是会被修改。

解决方案

方案1:使用user-event模拟真实用户行为

推荐使用@testing-library/user-event,它的交互逻辑完全贴近真实用户,会自动尊重元素的disabled状态:

  1. 安装依赖:
npm install --save-dev @testing-library/user-event
  1. 修改测试代码:
import { describe, expect, it } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

describe('App button Problem', () => {
  const user = userEvent.setup();

  it('types in the input correctly', async () => {
      render(<input type={'text'} disabled={false}/> );
      const input : HTMLInputElement = screen.getByRole('textbox');
      await user.type(input, 'test');
      expect(input.value).toBe('test');
  });

  it('does not type in the input if disabled', async () => {
      render(<input type={'text'} disabled={true}/> );
      const input : HTMLInputElement = screen.getByRole('textbox');
      await user.type(input, 'test');
      expect(input.value).toBe('');
  }); 
});

方案2:调整断言逻辑(无需额外依赖)

如果不想引入新依赖,可以直接断言输入框的禁用状态,而不是依赖值的变化:

it('input should be disabled', async () => {
    render(<input type={'text'} disabled={true}/> );
    const input : HTMLInputElement = screen.getByRole('textbox');
    expect(input).toBeDisabled();
});

内容的提问来源于stack exchange,提问作者Chen Peleg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 01:03:17