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

Angular v16 Jest预览版搭配ESBuild,如何正确Mock JS模块?

Angular 16 Jest开发者预览版模块Mock解决方案

针对ESBuild构建导致的传统Jest Mock方法失效问题,以下是几个可行的解决思路:

1. 适配ESBuild的jest.mock写法

ESBuild会对模块进行树摇、重命名甚至内联处理,需要确保Mock语法符合ES模块规范:

  • 针对命名导出的模块,Mock时需添加__esModule: true标识:
jest.mock('module-name', () => ({
  __esModule: true,
  ...jest.requireActual('module-name'), // 保留其他原有导出
  targetMethod: jest.fn(() => 'mock-result')
}));
  • 针对默认导出,需显式指定default属性:
jest.mock('module-name', () => ({
  __esModule: true,
  default: jest.fn(() => 'default-mock-result')
}));

2. 利用Angular依赖注入替换模块逻辑

如果被Mock的模块是Angular服务或可封装为服务的逻辑,优先使用Angular的测试依赖注入机制:

  • 把目标模块的功能封装为Angular服务(比如TargetService)
  • 在测试用例中,用TestBed.overrideProvider提供Mock实现:
TestBed.configureTestingModule({
  providers: [
    {
      provide: TargetService,
      useValue: {
        targetMethod: jest.fn(() => 'mock-value')
      }
    }
  ]
});

这种方式完全适配Angular的构建流程,不会受ESBuild的模块处理影响。

3. 修改ESBuild配置保留模块标识

在Jest配置中调整ESBuild的转换选项,避免模块被内联或重命名:
在jest.config.ts(或jest.config.js)中,针对Angular builders的ESBuild配置添加如下参数:

export default {
  transform: {
    '^.+\\.(ts|js)$': [
      '@angular-builders/jest',
      {
        esbuildOptions: {
          keepNames: true, // 保留函数/类名称
          preserveModules: true // 不将模块内联到调用文件
        }
      }
    ]
  }
};

配置后,传统的jest.mock和jest.spyOn大概率能恢复正常,但可能会牺牲部分ESBuild的构建优化。

针对jest.spyOn不可写的临时解决方案

如果必须使用spyOn,可以先通过Object.defineProperty将目标方法改为可写:

import * as module from 'module-name';

// 先修改方法的可写性
Object.defineProperty(module, 'targetMethod', {
  writable: true
});

// 再进行spyOn
const spy = jest.spyOn(module, 'targetMethod').mockReturnValue('mock-result');

这种方式属于hack手段,仅建议在临时场景使用,长期还是推荐前面的规范方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 15:57:40