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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:40:57