You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 18:45:32