如何在Jest中Mock同文件内的React组件?
解决同文件命名导出组件的Mock问题
看起来你在测试Modal组件时,想Mock同文件里的Item组件,但当前的jest.mock写法有几个问题导致没生效,我来帮你修正并解释原因:
你的现有写法问题分析
jest.mock的第一个参数错误:你传了"Modal",但这个参数应该是模块的路径(也就是你的index.js文件路径),而不是组件名称。- 废弃的API:
require.requireActual已经被废弃,现在应该用jest.requireActual。 - 导出结构错误:你返回的对象把
Modal重新赋值了,但实际上应该保留真实的Modal,只替换Item为Mock组件。
正确的Mock方案
方案一:使用jest.mock全局Mock模块
这种方式会在模块导入阶段就完成Mock,适合整个测试文件的所有用例:
// index.test.js // 首先Mock当前模块 jest.mock('./index', () => { // 获取真实的模块导出内容 const actualModule = jest.requireActual('./index'); return { // 保留所有真实的导出,只替换需要Mock的Item ...actualModule, Item: jest.fn(() => <div>Mocked Item Component</div>) }; }); // 此时导入的Modal是真实组件,Item是Mock后的组件 import { Modal, Item } from './index'; import { render, screen } from '@testing-library/react'; test('Modal renders with mocked Item', () => { render(<Modal />); // 验证Item组件被调用 expect(Item).toHaveBeenCalled(); // 验证Modal中的Button是否正常渲染(可选) expect(screen.getByText('Great')).toBeInTheDocument(); });
方案二:使用jest.spyOn临时Mock
如果你只想在某个测试用例中MockItem,可以用jest.spyOn:
// index.test.js import * as Components from './index'; import { render, screen } from '@testing-library/react'; test('Modal renders with temporarily mocked Item', () => { // 创建Mock的Item组件并替换原导出 const mockItem = jest.spyOn(Components, 'Item') .mockImplementation(() => <div>Temporarily Mocked Item</div>); render(<Components.Modal />); // 验证Mock生效 expect(mockItem).toHaveBeenCalled(); expect(screen.getByText('Great')).toBeInTheDocument(); // 测试结束后恢复原组件 mockItem.mockRestore(); });
关键注意点
- 因为你用的是命名导出,Mock时必须保持导出结构的一致性:要么展开真实模块的所有导出再替换目标组件,要么用
spyOn精准替换单个导出。 - 确保你的测试环境(比如Jest + React Testing Library)已经正确配置,能够识别JSX语法。
内容的提问来源于stack exchange,提问作者Norfeldt
相关产品推荐
相关产品推荐

