如何在React Testing Library中获取HTML元素的ref属性并做断言
React Testing Library 如何断言元素绑定的ref值
你当前写法不生效的原因是:
screen.getByTestId返回的是浏览器原生DOM节点,React内部管理的ref属于React运行时的私有属性,不会直接挂载到原生DOM节点上,因此直接访问container.ref永远返回undefined,无法完成断言。
以下是可落地的实现方案,按推荐优先级排序:
方案1:优先推荐-测试时传入自定义ref接收组件内部ref值
如果你可以修改Wrapper组件的源码,只需给组件加一个可选的ref传递prop,将内部绑定container的ref同步到外部传入的ref即可:
组件侧修改示例
// Wrapper组件内部代码 const Wrapper = ({ onClose, noSwipe, containerRef }) => { const internalRef = useRef(null) // 同步ref状态到外部传入的containerRef useEffect(() => { if (containerRef) { containerRef.current = noSwipe ? null : internalRef.current } }, [noSwipe, containerRef]) return <div data-testid="container" ref={noSwipe ? null : internalRef}>...</div> }
测试代码修改
import React from 'react' it('element container ref should be null if prop noSwipe is passed', () => { const onCloseMock = jest.fn() const testContainerRef = React.createRef() render(<Wrapper onClose={onCloseMock} noSwipe containerRef={testContainerRef} />) expect(testContainerRef.current).toBeNull() })
方案2:无需改动ref逻辑,通过自定义data属性同步状态
如果不想调整原有ref相关逻辑,可以直接在container节点上新增data属性同步ref的状态,测试直接断言该属性即可:
组件侧修改示例
// Wrapper组件内部代码 const containerRef = useRef(null) // 渲染时直接绑定data属性标记ref状态 return <div data-testid="container" ref={noSwipe ? null : containerRef} data-ref-is-null={noSwipe} >...</div>
测试代码修改
it('element container ref should be null if prop noSwipe is passed', () => { const onCloseMock = jest.fn() render(<Wrapper onClose={onCloseMock} noSwipe />) const container = screen.getByTestId('container') expect(container).toHaveAttribute('data-ref-is-null', 'true') })
方案3:无修改组件权限时的临时方案
如果无法修改Wrapper组件的源码,可以通过劫持React.useRef调用获取内部ref实例,注意该方案耦合组件内部useRef的调用顺序,维护性较差不推荐长期使用:
import React from 'react' it('element container ref should be null if prop noSwipe is passed', () => { // 假设组件内部第一个调用的useRef就是绑定container的ref const refSpy = jest.spyOn(React, 'useRef').mockReturnValueOnce({ current: null }) const onCloseMock = jest.fn() render(<Wrapper onClose={onCloseMock} noSwipe />) expect(refSpy.mock.results[0].value.current).toBeNull() // 用完恢复useRef避免影响其他测试 refSpy.mockRestore() })
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

