如何用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
相关产品推荐
相关产品推荐

