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
相关产品推荐
相关产品推荐

