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

如何用TypeScript的Jest Mock/Spy模拟未导出内部函数?

解决Jest Mock未导出内部函数的问题

问题原因

你之前的方法失效的核心原因是:generateSuf 和 generatePre 是模块内未导出的私有函数,create 直接调用的是模块内部的函数引用,而非导出对象上的方法。jest.mock 覆盖导出对象或者 jest.spyOn 监听导出模块,都无法影响到内部的函数调用关系。

可行解决方案

方案1:重构代码,抽离私有函数到独立模块

这是最推荐的方案,既让测试更友好,也提升了代码可维护性:

  1. 新建工具模块(比如 src/services/flow-utils.ts),迁移并导出两个生成函数:
// flow-utils.ts
export async function generateSuf(id) {
  return id + 1;
}

export async function generatePre(id) {
  return id - 1;
}
  1. 在原模块中导入并使用:
// flow.ts
import { generateSuf, generatePre } from './flow-utils';

async function create(id: string, name: string) {
  const [suf, pre] = await Promise.all([generateSuf(id), generatePre(id)]);
  return suf + name + pre;
}

export { create };
  1. 测试时直接mock工具模块:
jest.mock('../../src/services/flow-utils', () => ({
  generateSuf: jest.fn().mockResolvedValue('1'),
  generatePre: jest.fn().mockResolvedValue('1'),
}));

it('should create a user', async () => {
  const result = await create('3', '4');
  expect(result).toBe('141');
});

方案2:使用 rewire 访问模块内部函数

如果不想重构代码,可以用 rewire 库修改模块内部私有变量:

  1. 安装依赖:
npm install --save-dev rewire
  1. 在测试文件中使用:
const rewire = require('rewire');
const flowModule = rewire('../../src/services/flow');

it('should create a user', async () => {
  // 替换内部的generateSuf和generatePre
  flowModule.__set__('generateSuf', jest.fn().mockResolvedValue('1'));
  flowModule.__set__('generatePre', jest.fn().mockResolvedValue('1'));
  
  // 从rewire模块中获取create方法
  const { create } = flowModule;
  const result = await create('3', '4');
  
  expect(result).toBe('141');
});

方案3:利用Jest模块模拟结合函数重写(不推荐,依赖实现细节)

此方法依赖Jest的模块处理逻辑,稳定性较差,仅适合临时场景:

import * as flowModule from '../../src/services/flow';

it('should create a user', async () => {
  // 用@ts-ignore规避TypeScript类型检查
  // @ts-ignore
  flowModule.generateSuf = jest.fn().mockResolvedValue('1');
  // @ts-ignore
  flowModule.generatePre = jest.fn().mockResolvedValue('1');
  
  const result = await flowModule.create('3', '4');
  expect(result).toBe('141');
});

注意:该方法在部分TypeScript编译配置下可能失效,因为未导出函数会被编译为模块内部私有变量,不会挂载到导出对象上。

内容的提问来源于stack exchange,提问作者Tomer Fikler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 00:57:16