- 我有一个使用 window.applicationCache 进行离线访问的 Web 应用程序。
- 我所有管理 appCache 的代码(例如检查/更新/交换缓存)都被封装到一个“缓存控制器”对象中。
我有单元测试来测试我的“缓存控制器”功能。为了测试,我暂时用我自己的模拟版本替换了本机 window.applicationCache 对象(因为我只想测试我的代码,而不是浏览器的 appCache 实现),例如。
window.applicationCache = { /* my appCache mock */ }; // unit tests run here. Code under test references window.applicationCache.
不久前(大约是 Chrome 16)这种方法非常有效。然后,Mac 和 Windows 平台上的 Chrome 17 删除了修补浏览器默认 window.applicationCache 属性的功能(奇怪的是,它在 Chrome for Linux 中对于所有版本(包括 Chrome 26)仍然可以正常工作)。当时,我为此记录了一个 Chromium 错误;但不幸的是,该错误报告仍被列为“未确认”。
无论如何,我刚刚将我的应用程序从传统的“浏览器全局变量”(即通过脚本标签加载 *.js 文件;所有 JS 对象都是全局的)移植到 AMD 样式的模块,使用require.js作为模块加载器。
AMD(或 CommonJS)的好处之一是依赖注入,您的代码在其中获得对任何依赖对象的本地引用,而不是依赖于全局引用,例如。
require(['foo'], function(Foo) {
var bar = new Foo();
});
...这使得对象模拟变得容易,因为您可以配置模块加载器以在测试模式下为“foo”传递一个模拟对象。
我曾希望通过转向依赖注入,我可以解决我的 applicationCache 问题(因为传递到我的模块中的“窗口”引用可以是全局窗口对象,也可以是模拟对象)。
但是我不确定如何让 require.js 将“窗口”作为依赖项注入到我的模块中?
是否可以(可能使用shim 配置?)定义一个“窗口”模块;然后可以将其传递给对全局“窗口”对象进行操作的任何代码?这样我就可以做这样的事情:
require(['???'], function(window) {
// 'window' here is the real window object, or for testing it's a mock window object
window.applicationCache.update();
});
...在哪里 '???' 是一个引用窗口对象的模块名称。
或者我是否需要定义我自己的模块来导出“窗口”,它可以为单元测试进行不同的映射,例如。
// window.js
define(function() {
return window; // real global window object
});
// window-mock.js
define(function() {
return {
applicationCache: { /* mock version of appCache */ }
}
});
// for unit testing, remap 'window' to the mock version
require.config({
map: {
"cache-controller": {
"window": "window-mock"
}
}
});
// cache-controller.js
require(['window'], function(window) {
window.applicationCache.update();
});