如何使用Jest和Testing Library测试React组件内传给子组件的内部函数
问题原因
- 元素选择错误:你用
component.getByText("name")获取到的是<InputGroup>渲染的<label>元素,标签元素没有value属性,触发change事件时自然会抛出「The given element does not have a value setter」的错误。 - 无效props传递:你定义的
Form组件没有声明接收onSubmit、functionality两个props,测试代码中传入的这两个参数完全不会生效,属于冗余代码。
正确测试方案
React Testing Library 主张测试用户可感知的行为,不需要单独测试组件内部定义的inputChange函数,只需要模拟用户输入的操作,验证后续UI表现符合预期,就可以间接验证inputChange函数的逻辑正确。
注意:你当前的InputGroup组件没有给<label>设置htmlFor属性,Form调用InputGroup时也没有传入id参数,导致标签和输入框没有关联,暂时可以通过类名选择输入框,也可以优化组件代码后使用语义化的getByLabelText查询。
正确测试代码如下:
import { render, fireEvent } from '@testing-library/react'; import Form from './Form'; describe("Form", () => { it("输入内容后inputChange会正确更新输入框值", () => { const { container, getByRole } = render(<Form />); // 通过类名获取输入框元素 const nameInput = container.querySelector('.input'); // 模拟输入操作 fireEvent.change(nameInput, { target: { value: "aaa" } }); // 验证输入框值符合预期 expect(nameInput).toHaveValue("aaa"); // 验证提交按钮状态 const submitBtn = getByRole('button', { type: 'submit' }); expect(submitBtn).not.toBeDisabled(); }); });
可选优化点
你原Form组件中提交按钮的禁用判断disabled={name === undefined}存在逻辑问题:name的初始值是空字符串,所以页面加载后提交按钮默认就是启用状态,不符合表单提交前必填项未填时禁用的常规需求,可以调整为disabled={!name.trim()}。
如果想要让组件语义更规范,方便测试查询,可以做两处小修改:
- Form组件调用InputGroup时传入id参数:
<InputGroup id="name" text="name" type="text" value={name} functionality={inputChange("name")}/>
- InputGroup组件给label增加htmlFor属性:
<label htmlFor={id}>{text}</label>
修改后就可以直接用getByLabelText('name')查询输入框,不需要依赖类名选择元素。
内容的提问来源于stack exchange,提问作者Chochomona
相关产品推荐
相关产品推荐

