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

使用Jest测试React按钮点击渲染文本组件时遇元素查找失败问题

问题原因与解决方案

核心问题分析

  • 异步逻辑错误:组件中handleClick调用netflix()后立即同步更新media状态,但fetch是异步操作,此时document.current还未拿到新的后端数据,导致media无法正确赋值,自然渲染不出包含"About:"的文本。
  • 测试未处理异步与Mock:测试时直接发起真实请求,既依赖后端服务的运行状态,也没有等待异步请求完成就执行断言,所以找不到目标元素。

组件代码修复

修改异步逻辑,让handleClick等待数据返回后再更新状态,同时移除不必要的useRef,用state管理数据:

import React, { useState, useEffect } from "react";
import { isEmpty } from "lodash";

const ButtonSearch = () => {
  const [media, setMedia] = useState(null);

  // 改为返回Promise的异步函数,直接返回数据
  const fetchNetflixData = async () => {
    const res = await fetch("http://localhost:8080/netflix");
    return res.json();
  };

  // 初始化加载(可选,根据需求保留)
  useEffect(() => {
    fetchNetflixData();
  }, []);

  const handleClick = async () => {
    const data = await fetchNetflixData();
    setMedia({
      title: data.title,
      type: data.type,
      releaseYear: data.release_year,
      rating: data.rating,
      duration: data.duration,
      description: data.description,
    });
  };

  let text = (
    <div>
      {!isEmpty(media) ? (
        <p>
          Your random result is: {media.title}
          <br />
          {media.title} is a {media.type} that came out in {media.releaseYear}.
          It is {media.rating} rated, and is {media.duration} long. <br />
          About: <i>{media.description}</i>
        </p>
      ) : null}
    </div>
  );

  return (
    <div className="search">
      <button onClick={handleClick} type="submit">
        Search
      </button>
      <div role="textbox">{text}</div>
    </div>
  );
};

export default ButtonSearch;

测试代码修复

Mock fetch模拟后端返回数据,并用异步查询方法等待渲染完成:

import ButtonSearch from "../buttonSearch";
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
import userEvent from "@testing-library/user-event";

// Mock全局fetch
global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve({
      title: "Test Movie",
      type: "Movie",
      release_year: 2023,
      rating: "PG-13",
      duration: "120 mins",
      description: "A test description",
    }),
  })
);

describe("ButtonSearch测试", () => {
  test("点击按钮后渲染包含About:的文本", async () => {
    render(<ButtonSearch />);
    const button = screen.getByRole("button");
    
    await userEvent.click(button);
    
    // 使用findByText(异步查询方法)等待元素渲染
    expect(await screen.findByText("About:")).toBeInTheDocument();
  });
});

额外注意事项

  • 不要用useRef管理异步获取的渲染状态,React的state才是管理组件渲染数据的正确方式。
  • 测试时必须Mock异步请求,不能依赖真实后端服务,保证测试的独立性和稳定性。
  • 处理异步渲染的断言时,优先使用Testing Library提供的findBy*系列方法或waitFor包裹断言。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 03:31:06