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

条件渲染元素测试失败求助:React组件测试问题排查

问题描述

我是应用测试领域的新手,目前遇到一个无法定位原因的测试错误,希望得到帮助。我需要测试点击按钮后元素是否会在屏幕上显示或隐藏。

Greeting组件

export default function Greeting() {
  const [changedText, setChangedText] = useState(false);

  function changeTextHandler() {
    setChangedText(true);
  }

  return (
    <div>
      <h2>Hello World!</h2>
      {!changedText && <p>It's good to see you!</p>}
      {changedText && <p>Changed!</p>}
      <button onClick={changeTextHandler}>Change Text!</button>
    </div>
  );
}

失败的测试代码

describe("Greeting component", () => {
  test('renders "Changed!" if the button was clicked', () => {
    
    render(<Greeting />);

    const buttonElement = screen.getByRole("button");
    userEvent.click(buttonElement);

    const outputElement = screen.getByText("Changed!");
    expect(outputElement).toBeInTheDocument();
  });

  test('does not render "good to see you" if the button was clicked', () => {

    render(<Greeting />);

    const buttonElement = screen.getByRole("button");
    userEvent.click(buttonElement);

    const outputElement = screen.queryByText("good to see you", {
      exact: false,
    });
    expect(outputElement).toBeNull();
  });
})

错误描述

Greeting component › renders "Changed!" if the button was clicked

无法找到包含文本“Changed!”的元素。这可能是因为文本被多个元素拆分,此时您可以提供一个函数作为文本匹配器以提高灵活性。

Greeting component › does not render "good to see you" if the button was clicked

expect(received).toBeNull()

 Received: <p>It's good to see you!</p>

Package.json

{
  "name": "testes",
  "private": true,
  "version": "0.0.0",
  "type": "commonjs",
  "scripts": {
    "dev": "vite",
    "test": "jest",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@babel/core": "^7.21.4",
    "@babel/preset-env": "^7.21.4",
    "@babel/preset-react": "^7.18.6",
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^14.0.0",
    "@testing-library/user-event": "^14.4.3",
    "@types/react": "^18.0.28",
    "@types/react-dom": "^18.0.11",
    "@vitejs/plugin-react": "^3.1.0",
    "jest": "^29.5.0",
    "jest-environment-jsdom": "^29.5.0",
    "vite": "^4.2.0"
  }
}

问题原因与修复方案

测试失败的核心原因是**@testing-library/user-event v14+ 版本中,交互操作(如click)是异步的**,原代码没有等待点击完成就执行断言,导致React状态还未更新,测试查询的是旧状态下的元素。

修复后的测试代码

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Greeting from './Greeting';

describe("Greeting component", () => {
  test('renders "Changed!" if the button was clicked', async () => {
    const user = userEvent.setup(); // v14+ 需先创建用户实例
    
    render(<Greeting />);

    const buttonElement = screen.getByRole("button");
    await user.click(buttonElement); // 等待点击操作完成

    const outputElement = screen.getByText("Changed!");
    expect(outputElement).toBeInTheDocument();
  });

  test('does not render "good to see you" if the button was clicked', async () => {
    const user = userEvent.setup();
    
    render(<Greeting />);

    const buttonElement = screen.getByRole("button");
    await user.click(buttonElement); // 等待状态更新完成

    const outputElement = screen.queryByText("good to see you", {
      exact: false,
    });
    expect(outputElement).toBeNull();
  });
})

关键说明

  • v14+版本的@testing-library/user-event要求先调用userEvent.setup()创建用户实例,所有交互操作需通过该实例调用
  • 交互操作是异步的,必须用await等待完成,确保React状态更新后再执行元素查询和断言

内容的提问来源于stack exchange,提问作者Cláudio Vitor Dantas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 15:45:02