如何在Jest中Mock React Ref?scrollHeight测试未覆盖求助
如何Mock React Ref中的scrollHeight值?
背景代码
useState初始化代码
const [height, setHeight] = useState<number>( accordionRef.current?.scrollHeight ? accordionRef.current?.scrollHeight : 0, );
Ref定义
const accordionRef = useRef<HTMLDivElement | null>(null);
Ref使用的组件代码
<WrapperAccordion> <WrapperFlexButtonStrength> <WrapperButtonStrength> <Button fullWidth handleClick={() => handleOpenAccordion()} text="my label" typeButton="tertiary" /> </WrapperButtonStrength> </WrapperFlexButtonStrength> <WrapperStrengthMeter ref={accordionRef} height={height} data-is-open={openAccordion} > <InfoPasswordStrength contains={password.contains} length={password.length} minLength={minLength} /> </WrapperStrengthMeter> </WrapperAccordion>
问题说明
技术栈:React 18、styled-components、@testing-library/jest-dom 5.16.4
需要Mock accordionRef.current?.scrollHeight 的返回值,但始终无法实现,当前测试代码未覆盖该逻辑:
it("should render", async () => { jest.useFakeTimers(); jest.spyOn(global, "setTimeout"); render(<Wrapper />); const button = screen.getByRole("button", { name: "my label", }); fireEvent.click(button); await fireEvent.click(button); });
解决方案
方法1:初始化阶段Mock scrollHeight
由于useState在组件初始化时就会读取ref的scrollHeight,需要在render前提前Mock该属性:
it("should initialize height with ref's scrollHeight", () => { const mockScrollHeight = 200; // Mock HTMLDivElement原型的scrollHeight getter jest.spyOn(HTMLDivElement.prototype, 'scrollHeight', 'get').mockReturnValue(mockScrollHeight); render(<Wrapper />); // 给WrapperStrengthMeter添加data-testid="strength-meter"以便定位 const strengthMeter = screen.getByTestId('strength-meter'); expect(strengthMeter).toHaveStyle(`height: ${mockScrollHeight}px`); });
方法2:组件交互后Mock scrollHeight
如果setHeight是在handleOpenAccordion中触发的,需要在元素挂载后手动设置scrollHeight:
it("should update height when accordion toggles", async () => { const mockScrollHeight = 300; render(<Wrapper />); const button = screen.getByRole("button", { name: "my label" }); fireEvent.click(button); // 获取ref对应的DOM元素,手动设置scrollHeight const strengthMeter = screen.getByTestId('strength-meter'); Object.defineProperty(strengthMeter, 'scrollHeight', { value: mockScrollHeight }); // 再次触发交互以更新height fireEvent.click(button); expect(strengthMeter).toHaveStyle(`height: ${mockScrollHeight}px`); });
注意事项
- 给
WrapperStrengthMeter添加data-testid="strength-meter"属性,方便测试中定位元素; - styled-components生成的元素本质仍是HTMLDivElement,直接设置scrollHeight有效;
- 测试后恢复Mock避免影响其他用例:
afterEach(() => { jest.restoreAllMocks(); });
内容的提问来源于stack exchange,提问作者Rafael Silva
相关产品推荐
相关产品推荐

