如何使用React Testing Library测试父组件向子组件传递动态props场景
问题根因
首先梳理两处核心问题导致测试不通过:
- App组件的
textAreaParams是内部state管理,没有接收外部props,测试时给App传textAreaParams属性完全不会生效,默认逻辑里componentDidMount才会异步把state设为{message: 'Hello'} - 子组件TextArea将props的值拷贝到自身state,且没有添加props变化监听逻辑,props更新时子组件state不会同步更新;同时测试用
toHaveTextContent校验textarea内容不符合规范,textarea的输入值需要校验value属性 - 测试使用同步查询
getByPlaceholderText,第一次渲染时App的state里textAreaParams为空,TextArea还没渲染,同步查询会直接抛出找不到元素的错误
修复方案
分两种场景处理:
场景1:只修复测试,保留现有组件逻辑
如果不需要支持后续props动态更新,仅测App默认渲染逻辑,按如下调整测试:
- 用异步查询
findByPlaceholderText等待组件更新后再查询元素 - 校验textarea的
value属性,而非文本内容 - 不需要给App传自定义props,直接校验默认设置的
Hello值即可
场景2:支持父组件状态变化同步到子组件
如果需要子组件响应父组件props的动态更新,先修改子组件逻辑:
- 方案A:删除子组件内部的message state,直接使用props值,避免状态不同步
- 方案B:给子组件添加
componentDidUpdate生命周期,监听props变化时同步更新自身state
最终实现代码
调整后的App.test.js(对应场景1)
import App from './App'; import { cleanup, render } from '@testing-library/react'; describe('Rendering the App component and passing props to text area', () => { afterEach(cleanup); it('render the App component and check for the TextArea component', async () => { const { findByPlaceholderText } = render(<App />); const textarea = await findByPlaceholderText('test'); expect(textarea).toHaveValue('Hello'); }); });
优化后的TextArea.js(对应场景2,支持props动态更新,直接使用props无需冗余state)
import { Component } from 'react'; class TextArea extends Component { render() { return ( <div> <textarea rows="4" cols="50" value={this.props.params.message || ''} placeholder="test" onChange={() => {}} /> </div> ); } } export default TextArea;
如果要测试props动态更新的场景,可以用rerender方法重新渲染App,或者调用App实例的更新方法校验子组件值是否同步变化即可。
内容的提问来源于stack exchange,提问作者Murugesh Aravind
相关产品推荐
相关产品推荐

