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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 11:00:59