如何解决Jest+React Testing Library中自定义组件testID无法识别的问题
问题描述
我有如下自定义组件:
type MyCustomComponentProps = { a: string; b: number; testID?: string; // 希望通过这个props定位元素 } const MyCustomComponent = (props: MyCustomComponentProps) => { return // 任意渲染内容 }
在页面中使用该组件时写法如下:
<> <> <MyCustomComponent a={123} b={'something'} testID='my-test-id'/> </> </>
但测试时执行以下代码会失败,提示无法找到元素:
// 失败,因为找不到元素 expect(getByTestId('my-test-id').props.a).toBeStrictEqual(123)
补充说明:
更明确地说,我渲染了包含该自定义组件的MyScreen页面,想要用Testing Library的查询方法断言组件,代码如下:
it('bla bla bla',()=>{ const {getByTestId} = render(<MyScreen/>); const myComponent = getByTestId('my-test-id'); })
解决方法
Testing Library的getByTestId只能识别实际渲染到DOM/原生视图树中的元素上的测试标识:Web项目对应data-testid属性,React Native对应testID属性。你的自定义组件只是接收了testID参数,但没有把它传递给内部渲染的基础元素,所以测试工具找不到目标元素。
核心修复步骤
根据项目类型,把testID传递给组件内部的基础容器元素:
React Web项目
const MyCustomComponent = (props: MyCustomComponentProps) => { const { testID, ...rest } = props; // 将testID转为Web标准的data-testid属性,传递给最外层DOM元素 return ( <div data-testid={testID}> {/* 组件内部渲染内容 */} </div> ); }
React Native项目
const MyCustomComponent = (props: MyCustomComponentProps) => { const { testID, ...rest } = props; // 直接把testID传递给内部的原生容器组件 return ( <View testID={testID}> {/* 组件内部渲染内容 */} </View> ); }
关于断言组件props的补充
Testing Library的设计理念是基于用户可见的UI进行断言,而非直接检查组件props。如果一定要验证props是否正确传递,更合适的方式是用jest模拟自定义组件,检查它的调用参数:
import MyCustomComponent from './MyCustomComponent'; // 模拟自定义组件 jest.mock('./MyCustomComponent', () => ({ __esModule: true, default: jest.fn(() => <div />), })); it('传递正确的props给MyCustomComponent', () => { render(<MyScreen />); // 检查组件是否被传入了预期的props expect(MyCustomComponent).toHaveBeenCalledWith( expect.objectContaining({ a: 123, b: 'something', testID: 'my-test-id', }), expect.anything() ); });
内容的提问来源于stack exchange,提问作者Hans Yulian
相关产品推荐
相关产品推荐

