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

Jest测试API数据渲染的React组件时遇元素为null错误

React异步组件测试报错:received value must be an HTMLElement or an SVGElement

想要测试接收id props、调用API获取数据后渲染结构的React组件是否正常渲染对应结构,运行测试后收到错误:

received value must be an HTMLElement or an SVGElement.
Received has value: null

该问题确实与异步操作有关,必须等待组件完成API请求、渲染出目标元素后再执行检查。

测试代码

it('Some test', () => {
  const { container } = render(<SomeComponent id={1} />);
  const element = container.querySelector("someTag");
  expect(element).toBeVisible();
});

组件代码

const Somecomponent = ({ id }: Props) => {
  const { data, isLoading, isError, refetch } = someFunction(id);

  useEffect(() => {
    refetch();
  }, [id]);

  if (isLoading) {
    return <Loader />;
  }

  if (isError) {
    return <ErrorContent />;
  }

  if (!video) {
    return <InfoContent />;
  }

  return (
    <>
      <AnotherComponent {...data} />
    </>
  );
};

export default SomeComponent;

(注:AnotherComponent会根据data渲染对应内容)


解决方案

测试代码在组件完成API请求、渲染目标元素前就执行了查询,此时组件处于isLoading状态,仅渲染<Loader />,没有目标元素,导致querySelector返回null。需要等待异步渲染完成后再断言:

方法1:使用waitFor等待断言通过

waitFor会反复执行回调直到断言成立或超时,适配异步场景:

import { render, waitFor } from '@testing-library/react';

it('Some test', async () => {
  const { container } = render(<SomeComponent id={1} />);
  
  await waitFor(() => {
    const element = container.querySelector("someTag");
    expect(element).toBeVisible();
  });
});

方法2:用findBy*语法糖(更简洁)

findBy*是getBy*结合waitFor的语法糖,会自动等待元素出现:

import { render, screen } from '@testing-library/react';

it('Some test', async () => {
  render(<SomeComponent id={1} />);
  // 优先用语义化查询,比如role、testId,比querySelector更可靠
  const element = await screen.findByTestId("your-element-test-id"); 
  expect(element).toBeVisible();
});

额外优化建议

  • Mock API请求:测试时不要依赖真实接口,用Jest mock掉someFunction,保证测试稳定且快速:
    jest.mock('./path-to-someFunction', () => ({
      __esModule: true,
      default: () => ({
        data: { /* 模拟返回数据 */ },
        isLoading: false,
        isError: false,
        refetch: jest.fn(),
      }),
    }));
    
  • 避免直接用querySelector:优先使用screen.getByRole、screen.getByTestId等语义化查询方法,让测试更健壮,不易受DOM结构变化影响。

内容的提问来源于stack exchange,提问作者huhWell

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 23:10:31