使用Jest+TypeScript测试类静态方法时,Mock依赖静态方法遇ClassB未定义问题
Jest Mock静态方法时ClassB未定义问题解决
场景代码
ClassA 实现代码:
import { ClassB } from './classB' export class ClassA { public static async staticMethodA() { return await ClassB.staticMethodB(); } }
问题描述
编写staticMethodA的单元测试时,尝试MockClassB.staticMethodB以隔离测试逻辑,但运行时触发ClassB未定义错误。断点调试发现,代码中存在classB_1变量,但找不到预期的ClassB变量。
原测试代码:
describe('staticMethodA', () => { let classA; const mockStaticMethodB = jest.fn().mockResolvedValue({}); // 返回空对象 beforeAll(() => { // Mocking ClassB jest.mock('../src/classB', () => () => ({ ClassB: { staticMethodB: mockStaticMethodB } }))}; // 在Mock后导入ClassA,使其引用Mock classA = require('../src/classA'); } it('should call mockStaticMethodB', async () => { // require返回的是包含ClassA的对象 const actual = await classA.ClassA.staticMethodA(); expect(actual).toBe({}); // 断言返回空对象 } afterAll(() => { jest.unmock('../src/classB'); }); }
问题原因
原jest.mock的工厂函数写法错误:返回了一个模拟类构造函数的函数,但实际我们需要模拟的是直接导出的静态类对象——因为ClassA是通过import { ClassB } from './classB'直接导入静态类,而非通过实例化类得到对象。
解决方案
1. 修正Jest Mock写法
将jest.mock的工厂函数改为直接返回包含ClassB的导出对象,而非构造函数:
describe('staticMethodA', () => { let ClassA; const mockStaticMethodB = jest.fn().mockResolvedValue({}); beforeAll(() => { // 正确模拟classB模块的导出结构 jest.mock('../src/classB', () => ({ ClassB: { staticMethodB: mockStaticMethodB } })); // 解构导入ClassA,简化后续调用 ({ ClassA } = require('../src/classA')); }); it('should call mockStaticMethodB and return the mock value', async () => { const actual = await ClassA.staticMethodA(); // 断言Mock方法被调用 expect(mockStaticMethodB).toHaveBeenCalled(); // 对象断言用toEqual(递归比较属性),而非toBe(比较引用) expect(actual).toEqual({}); }); afterAll(() => { jest.unmock('../src/classB'); }); });
2. 额外注意事项
- 避免模块缓存问题:如果测试中多次导入模块,可使用
jest.isolateModules包裹导入逻辑,确保每次测试都使用全新的Mock:
beforeAll(() => { jest.isolateModules(() => { jest.mock('../src/classB', () => ({ ClassB: { staticMethodB: mockStaticMethodB } })); ({ ClassA } = require('../src/classA')); }); });
- 断言对象时必须用
toEqual:toBe仅比较对象引用,无法匹配两个内容相同但内存地址不同的对象。 - 增加Mock调用断言:通过
expect(mockStaticMethodB).toHaveBeenCalled()验证逻辑的执行路径是否符合预期。
内容的提问来源于stack exchange,提问作者rsegda
相关产品推荐
相关产品推荐

