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

Angular9项目用Jasmine做spy时出现uuid is not declared configurable错误

问题原因

Angular 8 升级到 9 后默认启用 Ivy 编译器,同时模块输出默认采用 ES 模块规范。和之前使用的 CommonJS 规范不同,ES 模块的导出属性默认configurable属性为false,禁止外部修改属性描述符。Jasmine 的spyOnProperty以及spyOn都需要修改目标属性的配置,因此会抛出uuid is not declared configurable错误。
另外你此处监听的uuid是普通导出函数,不需要使用针对 getter 的spyOnProperty方法。

可行解决方案
  • 方案1:临时修改模块导出属性的可配置性
    在 spy 代码前新增一行手动修改属性配置,不需要改动业务代码,适配成本最低,测试代码修改如下:
import * as utils from 'app/shared/utils';

it('sample test',
fakeAsync(() => {
  // 新增这行手动设置为可配置
  Object.defineProperty(utils, 'uuid', { configurable: true });
  const uuidFunc = jasmine.createSpy('uuid').and.returnValue('12345');
  // 普通函数直接用spyOn即可,不需要spyOnProperty
  spyOn(utils, 'uuid').and.callFake(uuidFunc);
  // 原有业务逻辑
  ......
  • 方案2:调整工具模块的导出方式
    修改app/shared/utils.ts的导出逻辑,将所有工具方法挂载到一个默认导出的对象上,从根本上避免 ES 模块直接导出的限制:
// utils.ts 修改后代码
function uuid(): string {
   const bytes = new Uint32Array(4);
   return bytes;
 }
// 所有工具方法统一通过默认对象导出
export default {
  uuid,
  // 其他工具方法按同样格式添加
}

测试代码导入方式同步调整:

// 改为导入默认对象
import utils from 'app/shared/utils';

it('sample test',
fakeAsync(() => {
  const uuidFunc = jasmine.createSpy('uuid').and.returnValue('12345');
  spyOn(utils, 'uuid').and.callFake(uuidFunc);
  ......
  • 方案3:采用 Angular 依赖注入管理工具方法
    将 uuid 等通用工具方法封装为可注入服务,测试时直接替换服务实现即可,符合 Angular 最佳实践:
// 新增工具服务
@Injectable({ providedIn: 'root' })
export class UtilsService {
  uuid(): string {
    const bytes = new Uint32Array(4);
    return bytes;
  }
}

测试时直接配置 mock 服务即可,不需要使用 spy 监听模块导出:

TestBed.configureTestingModule({
  providers: [
    { provide: UtilsService, useValue: { uuid: () => '12345' } }
  ]
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 03:54:06