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

如何用Vitest测试接收setState作为Props的React组件?解决渲染报错

React组件测试:修复接收setState类props的组件渲染问题

问题背景

刚开始学习React测试,不清楚如何测试需要state和setState作为props的组件。见过jest.fn()的示例,但不确定Vitest中Mock的用法,当前测试的Popover组件无法正常渲染。

目标组件(Popover.jsx)

//Popover.jsx
const Popover = ({ setShowPopover, setIsEditing, setInputDisabled }) => {
  return (
    <>
      <div
        data-testid="edit-task-btn"
        onClick={() => {
          setIsEditing(true);
          setShowPopover(false);
          setInputDisabled(false);
        }}>
        Edit
      </div>
    </>
  );
};

当前测试代码(Popover.test.jsx)

///Popover.test.jsx
it('renders correctly and handles Edit', () => {
  const setIsEditingMock = () => {
    true;
  };

  const setShowPopoverMock = () => {
    false;
  };

  const setInputDisabledMock = () => {
    false;
  };

  render(
    <Popover
      setIsEditing={setIsEditingMock}
      setShowPopover={setShowPopoverMock}
      setInputDisabled={setInputDisabledMock}
    />
  );

  screen.debug();

  const editButton = screen.getByTestId('edit-task-btn');
  expect(editButton).toBeInTheDocument();
})

错误信息

TestingLibraryElementError: Unable to find an element by: [data-testid="edit-task-btn"]

Ignored nodes: comments, script, style
<body>
  <div />
</body>

修复方案及解释

1. 核心问题:组件未导出

测试失败的直接原因是Popover组件没有被导出,导致测试文件无法正确引入并渲染组件。

2. 第一步:给组件添加导出

修改Popover.jsx,添加导出语句:

//Popover.jsx
// 具名导出
export const Popover = ({ setShowPopover, setIsEditing, setInputDisabled }) => {
  return (
    <>
      <div
        data-testid="edit-task-btn"
        onClick={() => {
          setIsEditing(true);
          setShowPopover(false);
          setInputDisabled(false);
        }}>
        Edit
      </div>
    </>
  );
};

// 或者使用默认导出:
// export default Popover;

注意测试文件中要对应使用import { Popover } from './Popover'或import Popover from './Popover'。

3. 第二步:使用Vitest的vi.fn()优化Mock函数

Vitest中模拟setState类props的方式和Jest一致,用vi.fn()创建Mock函数,既能满足组件渲染需求,还能验证函数的调用逻辑:

修改测试代码:

///Popover.test.jsx
import { render, screen, fireEvent } from '@testing-library/react';
import { Popover } from './Popover'; // 确保导入路径和导出方式匹配

it('renders correctly and triggers correct callbacks on Edit click', () => {
  // 创建Vitest Mock函数
  const setIsEditingMock = vi.fn();
  const setShowPopoverMock = vi.fn();
  const setInputDisabledMock = vi.fn();

  render(
    <Popover
      setIsEditing={setIsEditingMock}
      setShowPopover={setShowPopoverMock}
      setInputDisabled={setInputDisabledMock}
    />
  );

  // 验证组件渲染
  const editButton = screen.getByTestId('edit-task-btn');
  expect(editButton).toBeInTheDocument();
  expect(editButton).toHaveTextContent('Edit');

  // 模拟点击,验证回调函数的调用参数和次数
  fireEvent.click(editButton);
  expect(setIsEditingMock).toHaveBeenCalledWith(true);
  expect(setShowPopoverMock).toHaveBeenCalledWith(false);
  expect(setInputDisabledMock).toHaveBeenCalledWith(false);
})

关键知识点

  • vi.fn()的作用:和Jest的jest.fn()功能完全一致,用于创建Mock函数,可追踪函数的调用次数、传入参数等,是测试回调类props的标准方式。
  • 组件导出规则:React组件必须通过export导出,才能在其他文件(包括测试文件)中被引入使用。
  • fireEvent的用法:@testing-library/react提供的工具,用于模拟用户交互(如点击、输入),验证组件的交互逻辑是否符合预期。

内容的提问来源于stack exchange,提问作者min-coding

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 09:53:16