Jasmine+Karma+Istanbul测试报错:window/self未定义
我之前在搭建类似的单元测试环境时也踩过这个坑,结合你已经用Browserify解决Node模块适配的前提,这本质上是Karma在Node环境中模拟浏览器全局变量不完整导致的,给你几个针对性的解决办法:
1. 补全Karma的全局变量配置
你的代码大概率同时依赖了window和self(比如一些浏览器端的库或者API调用),只单独设置其中一个肯定会漏。打开你的karma.conf.js,把常用的浏览器全局变量都映射到Node的global对象上:
module.exports = function(config) { config.set({ // 其他已有配置(比如frameworks、files、preprocessors等) globals: { window: global, self: global, document: {}, // 如果代码用到document,模拟空对象即可 navigator: {} // 同理,按需添加其他浏览器全局对象 } }); };
这样Karma在运行测试时,会把这些全局变量注入到测试环境中,替代浏览器原生的全局对象。
2. 确保Browserify与Karma的全局配置兼容
因为你用了Browserify打包测试代码,可能存在全局变量被Browserify重写的情况。可以在Karma的browserify配置里,用browserify-global-shim插件强制注入全局变量:
首先安装依赖:
npm install browserify-global-shim --save-dev
然后在karma.conf.js中配置:
module.exports = function(config) { config.set({ // 其他配置... browserify: { transform: ['browserify-global-shim'], globalShim: { window: 'global', self: 'global' } } }); };
这个插件会在Browserify打包过程中,把代码里对window/self的引用替换为Node的global对象。
3. 排查业务/测试代码中的硬编码依赖
如果上面的配置还是没解决问题,建议检查你的业务代码或者测试用例,有没有直接硬编码使用window/self的地方。可以添加一个简单的兼容层来统一全局对象引用:
// 在测试入口或者业务代码的公共模块中添加 const globalContext = (() => { if (typeof window !== 'undefined') return window; if (typeof self !== 'undefined') return self; return global; })();
之后用globalContext代替代码中直接的window/self调用,这样不管在浏览器还是Node测试环境都能正常工作。
4. 验证Istanbul配置无冲突
有时候Istanbul的代码覆盖率配置会干扰Karma的全局变量注入,确保你的.istanbul.yml或者package.json中的istanbul配置没有覆盖Karma的设置。比如可以在package.json的test命令里明确指定Karma配置文件,避免歧义:
"scripts": { "test": "karma start ./karma.conf.js --coverage" }
内容的提问来源于stack exchange,提问作者Kyl San Antonio

