Jest中无法Mock导入模块返回值,异步导入致函数未定义
问题原因
你遇到的错误确实是异步工厂函数导致的。Jest 在加载模块时是同步执行的,而你给jest.mock传了一个带async/await的异步工厂函数,它会返回 Promise 对象,而非 Jest 期望的模块导出结构。这就导致被 mock 的random模块实际变成了 Promise,所有导出函数自然都是undefined,进而出现shuffle is not a function的错误。
解决方案
下面提供几种可行的解决思路,你可以根据代码场景选择:
1. 同步导入 Foo(最直接方案)
如果Foo和random模块之间没有循环依赖,直接在jest.mock的工厂函数里用require同步导入Foo即可,避开异步问题:
jest.mock('./random', () => { // 用 require 同步导入 Foo,不受 jest.mock 提升机制影响 const { Foo } = require('./Foo'); return { // 保留原模块的其他导出内容 ...jest.requireActual('./random'), // 替换 shuffle 的 mock 实现 shuffle: jest.fn().mockReturnValue([new Foo()]), }; });
2. 动态 Mock(适配循环依赖场景)
如果Foo和random存在循环依赖,同步require会触发报错,可以用jest.resetModules()配合动态导入实现:
// 每次测试前重置模块缓存,避免旧 mock 干扰 beforeEach(async () => { jest.resetModules(); const { Foo } = await import('./Foo'); // 动态 mock random 模块 jest.mock('./random', () => ({ ...jest.requireActual('./random'), shuffle: jest.fn().mockReturnValue([new Foo()]), })); }); test('测试目标方法1', async () => { // 每次测试重新导入待测试类,确保使用最新 mock const { YourTestClass } = await import('./YourTestClass'); const instance = new YourTestClass(); // 执行测试逻辑 }); test('测试目标方法2', async () => { const { YourTestClass } = await import('./YourTestClass'); const instance = new YourTestClass(); // 执行测试逻辑 });
3. 延迟设置 Mock 返回值(更灵活)
如果不需要在jest.mock阶段就创建Foo实例,可以先把shuffle mock 为空函数,再在测试前置钩子或用例里设置返回值:
// 先将 shuffle mock 为 Jest 函数,保留原模块其他导出 jest.mock('./random', () => ({ ...jest.requireActual('./random'), shuffle: jest.fn(), })); // 正常导入所需模块 import { shuffle } from './random'; import { Foo } from './Foo'; import { YourTestClass } from './YourTestClass'; // 在测试前统一设置返回值 beforeEach(() => { (shuffle as jest.Mock).mockReturnValue([new Foo()]); }); test('测试目标方法1', () => { const instance = new YourTestClass(); // 测试逻辑 }); test('测试目标方法2', () => { const instance = new YourTestClass(); // 测试逻辑 });
内容的提问来源于stack exchange,提问作者Forseti
相关产品推荐
相关产品推荐

