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

如何在Jest中Mock内部实例化的类方法完成单元测试?

解决Jest Mock内部实例化类方法的问题

当被测试服务内部自行实例化依赖类时,直接使用spyOn或普通jest.mock无法生效,因为新创建的实例不会关联到你之前mock的对象。下面是两种可行的解决方案:

方案一:Mock整个依赖类模块

通过jest.mock替换整个依赖模块的导出,让被测试代码中new ExampleService()得到的是我们预设的mock实例。

示例代码

// 先mock ExampleService模块,必须在import之前调用
jest.mock('./example.service', () => {
  return {
    ExampleService: jest.fn().mockImplementation(() => ({
      // 预设findUsers的返回值,匹配Promise<Users[]>类型
      findUsers: jest.fn().mockResolvedValue([
        { id: 1, isHomeOwner: true },
        { id: 2, isHomeOwner: false }
      ])
    }))
  };
});

import { ToBeTestedService } from './toBeTested.service';
import { ExampleService } from './example.service';

// 类型断言,方便后续操作mock对象
const MockExampleService = ExampleService as jest.Mock;

describe('ToBeTestedService', () => {
  let testedService: ToBeTestedService;

  beforeEach(() => {
    // 重置mock状态,避免测试用例间污染
    MockExampleService.mockClear();
    testedService = new ToBeTestedService();
  });

  it('筛选出所有房主用户', async () => {
    const result = await testedService.findHomeOwners();
    
    // 验证findUsers方法被调用
    expect(MockExampleService.mock.instances[0].findUsers).toHaveBeenCalled();
    // 验证结果符合预期
    expect(result).toEqual([{ id: 1, isHomeOwner: true }]);
  });

  it('处理空用户列表的情况', async () => {
    // 给当前测试用例单独设置mock返回值
    MockExampleService.mockImplementation(() => ({
      findUsers: jest.fn().mockResolvedValue([])
    }));

    const result = await testedService.findHomeOwners();
    expect(result).toEqual([]);
  });
});

方案二:SpyOn依赖类的原型方法

当你用jest.mock自动mock整个模块后,可以通过spyOn该类的原型方法,让所有新实例都使用mock实现。

示例代码

// 自动mock ExampleService模块
jest.mock('./example.service');

import { ToBeTestedService } from './toBeTested.service';
import { ExampleService } from './example.service';

describe('ToBeTestedService', () => {
  let testedService: ToBeTestedService;
  let mockFindUsers: jest.Mock;

  beforeEach(() => {
    // 创建mock方法,指定返回类型
    mockFindUsers = jest.fn().mockResolvedValue([{ id: 1, isHomeOwner: true }]);
    // SpyOn原型上的findUsers方法,替换为mock实现
    jest.spyOn(ExampleService.prototype, 'findUsers').mockImplementation(mockFindUsers);
    
    testedService = new ToBeTestedService();
  });

  afterEach(() => {
    // 恢复所有mock,避免影响其他测试
    jest.restoreAllMocks();
  });

  it('正确返回房主用户', async () => {
    const result = await testedService.findHomeOwners();
    
    expect(mockFindUsers).toHaveBeenCalled();
    expect(result).toEqual([{ id: 1, isHomeOwner: true }]);
  });
});

关键注意事项

  • jest.mock必须在模块import之前调用,否则原模块会先被加载,mock无法生效。
  • TypeScript环境下需要用jest.Mock类型断言处理mock对象,避免类型报错。
  • 测试用例之间要重置或恢复mock状态,防止测试污染。

内容的提问来源于stack exchange,提问作者quefro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:15:40