Jest:模块同时存在默认导出组件与命名导出时如何Mock?
如何同时Mock ES6模块的默认导出组件与命名导出函数
我之前也碰到过一模一样的问题,尤其是刚开始用Jest Mock ES6模块的时候,很容易在默认导出和命名导出的处理上踩坑。下面给你两种靠谱的解决方案,都是我实际项目里用过的:
方法一:使用jest.mock工厂函数一次性Mock所有导出
这是最常用的方式,直接在测试文件顶部定义Mock,一次性覆盖默认导出和命名导出。关键是要加上__esModule: true标识,让Jest正确识别这是ES6模块结构。
假设你的原模块MyModule.js结构是这样的:
import React from 'react'; export default class MyComponent extends React.Component { render() { return <div>Original Component</div>; } } export const myNamedFunction = () => { return 'original result'; };
测试文件中的Mock写法:
import React from 'react'; import { render } from '@testing-library/react'; import OtherComponent from './OtherComponent'; // 依赖MyModule的组件 import MyComponent, { myNamedFunction } from './MyModule'; // 核心Mock代码 jest.mock('./MyModule', () => ({ __esModule: true, // 必须!告诉Jest这是ES6模块 default: jest.fn(() => <div>Mocked MyComponent</div>), // Mock默认导出的组件 myNamedFunction: jest.fn(() => 'mocked function result'), // Mock命名导出的函数 })); describe('OtherComponent', () => { it('应该渲染Mock的组件并调用Mock的函数', () => { const { getByText } = render(<OtherComponent />); // 验证Mock组件被渲染 expect(getByText('Mocked MyComponent')).toBeInTheDocument(); // 验证命名函数被调用 expect(myNamedFunction).toHaveBeenCalled(); }); });
方法二:动态修改Mock对象(适合多测试用例场景)
如果需要在不同测试用例中修改Mock的返回值或行为,可以先Mock整个模块,再动态设置默认导出和命名导出的Mock内容:
import React from 'react'; import { render } from '@testing-library/react'; import OtherComponent from './OtherComponent'; import * as MyModule from './MyModule'; // 用*导入整个模块 // 先Mock整个模块 jest.mock('./MyModule'); // 定义Mock内容 const MockedMyComponent = jest.fn(() => <div>Default Mock Component</div>); const mockedMyNamedFunction = jest.fn(() => 'default mocked result'); // 绑定到Mock模块上 MyModule.default = MockedMyComponent; MyModule.myNamedFunction = mockedMyNamedFunction; describe('OtherComponent', () => { it('使用默认Mock内容', () => { render(<OtherComponent />); expect(MockedMyComponent).toHaveBeenCalled(); expect(mockedMyNamedFunction).toHaveReturnedWith('default mocked result'); }); it('动态修改Mock内容', () => { // 重新设置Mock返回值 MockedMyComponent.mockReturnValue(<div>Updated Mock Component</div>); mockedMyNamedFunction.mockReturnValue('updated mocked result'); const { getByText } = render(<OtherComponent />); expect(getByText('Updated Mock Component')).toBeInTheDocument(); expect(mockedMyNamedFunction).toHaveReturnedWith('updated mocked result'); }); });
常见坑点提醒
- 忘记加
__esModule: true:这是最容易犯的错误,Jest默认按CommonJS模块处理,不加这个标识的话,默认导出会被当成default属性,导致组件中引用的默认组件没有被Mock到。 - 导入方式不匹配:如果你的组件中用
require导入ES6模块,Mock的结构也需要调整,但现在React项目几乎都用ES6的import,所以上面的方法基本都适用。 - Mock函数未正确初始化:确保用
jest.fn()创建Mock函数,而不是普通函数,这样才能调用toHaveBeenCalled()这类断言方法。
内容的提问来源于stack exchange,提问作者user2117153
相关产品推荐
相关产品推荐

