如何在Jest中监视构造函数中实例化的类
问题描述
我有一段异步业务代码:
async function(paramA?: string): Promise<void> { if (paramA === undefined) { paramA = this.randomString(); } this.funnel.loginFunnel(Status.Pending); await this.tracker.flush(); this.service.call(this.name, paramA, code); }
其中tracker和service是在类的构造函数中初始化的:
constructor(params: Params) { this.tracker = new Tracker(params); this.service = new Service(params, this.tracker); }
这是纯JS代码,非React等框架。我需要验证两个逻辑:
loginFunnel是否确实以Status.Pending为参数被调用service.call是否传入了正确的paramA参数
我尝试用Jest的jest.mock导入Tracker类做测试:
jest.mock('../tracker'); service.call(); expect(Tracker).toHaveBeenCalledTimes(1);
但测试抛出错误:
expect(received).toHaveBeenCalledTimes(expected) Matcher error: received value must be a mock or spy function Received has type: function Received has value: [Function Tracker]
解决方法
1. 正确Mock依赖类并获取实例
jest.mock会自动替换目标类为Mock,但要验证实例方法的调用,得先拿到Mock类创建的实例。同时因为Service也是在构造函数中实例化的,需要一起Mock。
第一步:Mock所有依赖类
// 自动Mock Tracker和Service类,Jest会生成对应的Mock构造函数 jest.mock('../tracker'); jest.mock('../service');
第二步:创建被测实例并提取Mock对象
// 准备测试用参数 const testParams = { /* 填写你的测试参数 */ }; // 创建被测类的实例 const testInstance = new YourClassName(testParams); // 提取Tracker的Mock实例(构造函数调用后,实例会存在mock.instances里) const mockTracker = Tracker.mock.instances[0]; // 提取Service的Mock实例 const mockService = Service.mock.instances[0]; // 给funnel手动创建Mock(如果funnel不是构造函数初始化的,直接替换成Spy) testInstance.funnel = { loginFunnel: jest.fn() }; // 让tracker的flush返回resolved Promise,避免异步阻塞 mockTracker.flush.mockResolvedValue(undefined);
2. 验证loginFunnel的调用
调用被测方法后,直接断言loginFunnel的调用参数:
// 调用被测的异步方法 await testInstance.yourAsyncMethodName(); // 验证loginFunnel以Status.Pending为参数调用 expect(testInstance.funnel.loginFunnel).toHaveBeenCalledWith(Status.Pending);
3. 验证service.call的参数
分两种场景测试:传入paramA和不传paramA的情况:
// 场景1:传入自定义paramA const testParamA = 'custom-test-value'; await testInstance.yourAsyncMethodName(testParamA); // 断言call方法的参数是否正确 expect(mockService.call).toHaveBeenCalledWith(testInstance.name, testParamA, code); // 场景2:不传入paramA,此时会调用randomString生成值 // 先mock randomString返回固定值,避免随机结果影响测试 testInstance.randomString = jest.fn().mockReturnValue('random-generated-value'); await testInstance.yourAsyncMethodName(); expect(mockService.call).toHaveBeenCalledWith(testInstance.name, 'random-generated-value', code);
关于你之前的报错原因
你直接断言Tracker构造函数的调用次数时出错,是因为jest.mock生成的Mock构造函数,需要确保你导入的是Mock后的类。正确的构造函数调用断言应该是:
// 验证Tracker构造函数被调用了1次,参数是testParams expect(Tracker).toHaveBeenCalledTimes(1); expect(Tracker).toHaveBeenCalledWith(testParams);
如果还是报错,检查是否在测试文件中正确导入了Tracker类,或者是否有其他地方重新导入了原始类导致Mock失效。
内容的提问来源于stack exchange,提问作者Juanma Perez
相关产品推荐
相关产品推荐

