如何延迟Angular测试启动,等待异步第三方库加载完成?
Angular 10 延迟测试启动以等待异步第三方库加载完成
我使用Angular 10开发,许多组件依赖一个私有第三方库——它会异步注入到window对象中。测试运行前必须等待该库的Promise完成,但测试运行器无法自动等待这个异步流程。
在test.ts中我尝试了以下代码:
LoadAnnoyingBigBiznessStuff().then(() => { getTestBed().initTestEnvironment( BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { teardown: { destroyAfterEach: false }, } ); });
但测试运行时抛出错误:
Error: Need to call TestBed.initTestEnvironment() first
问题出在脚本会在Promise解析完成前就执行完毕,且无法使用顶层await来等待异步调用完成。
解决方案1:基于Karma的等待方案
如果使用Karma作为测试运行器,可以通过配置钩子+循环检测的方式实现延迟启动:
- 修改
karma.conf.js,给客户端传递等待标志:
module.exports = function(config) { config.set({ client: { args: ['--wait-for-lib'] } }); };
- 重构
test.ts,先等待库加载完成再初始化测试环境:
// 定义同步检测库是否加载完成的函数 function waitForLibReady() { return new Promise(resolve => { const checkLib = () => { // 替换成第三方库注入到window的实际属性名 if (window['AnnoyingBigBiznessStuff']) { resolve(); } else { setTimeout(checkLib, 100); } }; checkLib(); }); } // 异步初始化流程 (async () => { await LoadAnnoyingBigBiznessStuff(); await waitForLibReady(); // 初始化测试环境 getTestBed().initTestEnvironment( BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { teardown: { destroyAfterEach: false }, } ); // 手动加载并执行所有测试文件 const context = require.context('./', true, /\.spec\.ts$/); context.keys().map(context); })();
解决方案2:拦截测试文件加载,延迟执行
无需修改Karma配置,通过拦截测试文件的加载时机,等异步流程完成后再执行:
declare const require: any; const originalRequire = require; let pendingTestFiles: string[] = []; // 拦截测试文件的加载请求,先收集不执行 require = (path: string) => { if (path.match(/\.spec\.ts$/)) { pendingTestFiles.push(path); return () => {}; } return originalRequire(path); }; // 等待第三方库加载完成后,初始化测试环境并执行测试 LoadAnnoyingBigBiznessStuff().then(() => { getTestBed().initTestEnvironment( BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { teardown: { destroyAfterEach: false }, } ); // 加载并执行所有收集到的测试文件 pendingTestFiles.forEach(filePath => originalRequire(filePath)); }); // 触发测试文件的收集逻辑 const context = require.context('./', true, /\.spec\.ts$/); context.keys().map(context);
注意事项
- 务必将
window['AnnoyingBigBiznessStuff']替换为第三方库实际注入到window对象的属性名称 - 如果你的测试文件导入方式不是
require.context,需要对应调整收集和执行逻辑 - 确保
LoadAnnoyingBigBiznessStuff()返回的Promise能准确标识库加载完成的状态
内容的提问来源于stack exchange,提问作者spots
相关产品推荐
相关产品推荐

