Jest TS mock Client实例返回undefined数组而非预期mock值问题
问题根因
测试失败核心是三个写法问题:
- mock对象属性覆盖:
jest.mock('@src/client')会自动生成Client类的mock,其原型上的getTasks方法默认是返回undefined的空mock函数。你在mockImplementation返回对象时,先定义了自定义的getTasks实现,再通过...mockClient.prototype展开原型属性,原型上默认的getTasks会直接覆盖你前面写的自定义实现,最终调用getTasks时拿到的是默认返回的undefined,经await和flat()处理后就得到了包含undefined的数组。 - 异步方法mock不符合真实签名:业务代码中
client.getTasks是异步请求方法,你用mockReturnValue返回同步值,虽然await同步值不会直接报错,但和真实方法的Promise返回行为不一致,容易埋下隐性问题。 - 变量名歧义:测试用例内部声明实例时用了和外层mock类同名的
mockClient变量,容易引发作用域混淆。
修复后的测试代码
jest.mock('@src/client'); // 重命名避免歧义,明确这是mock的Client类 const MockClient = <jest.Mock<Client>>Client; describe('Helpers', () => { const mockTask = createMock<Task>(); beforeEach(() => { // 每次测试前重置mock,避免用例间状态污染 MockClient.mockReset(); MockClient.mockImplementation(() => { return { // 先展开原型,再写自定义方法,确保自定义实现优先级更高 ...MockClient.prototype, // 异步方法用mockResolvedValue返回Promise,和真实行为对齐 getTasks: jest.fn().mockResolvedValue([mockTask]) }; }); }); it('getAllTasks() 应返回所有站点下的任务集合', async () => { const mockSites = [createMock<Site>()]; // 变量名区分mock类和实例 const clientInstance = new MockClient({ // constructor params here }); const tasks = await getAllTasks(mockSites, clientInstance); expect(tasks).toEqual([mockTask]); // 可选:断言getTasks被正确调用,入参匹配站点id expect(clientInstance.getTasks).toHaveBeenCalledWith(mockSites[0].id); }); });
关键修改点说明
- 调整对象展开顺序:先展开原型属性,再定义自定义方法,保证自定义mock实现不会被原型默认属性覆盖
- 异步方法改用
mockResolvedValue:返回Promise类型结果,和真实getTasks的异步行为完全一致 - 增加mock重置逻辑:在
beforeEach中重置mock实现,避免多个测试用例之间的mock状态互相干扰 - 重命名变量区分mock类和实例:消除同名变量带来的作用域歧义
- 可选增加调用断言:验证方法入参传递正确,覆盖更多测试场景
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

