2013-02-25 59 views
17
  1. 我有一个web应用程序,它使用window.applicationCache为 脱机访问。
  2. 我管理appCache (例如,检查/更新/交换缓存)的所有代码都封装在一个“缓存控制器”对象中。
  3. 我有单元测试来测试我的 “缓存控制器”功能。对于测试,我暂时用 替换本机window.applicationCache对象与我自己的模拟 版本(因为我只想测试我的代码,而不是浏览器 appCache实现),例如。模拟全局窗口对象中的require.js

    window.applicationCache = { /* my appCache mock */ }; 
    // unit tests run here. Code under test references window.applicationCache. 
    

前一段时间(大约镀铬16)这种方法非常完美。然后,Chrome 17在Windows平台上的Mac &中删除了修补浏览器的默认window.applicationCache属性的功能(但奇怪的是,Chrome for Linux的所有版本(包括Chrome 26在内)都可以正常工作。当时,我logged a Chromium bug为此;但不幸的是,该错误报告仍列为“未经证实”。

无论如何,我只是使用require.js作为模块加载器,将我的应用程序从传统的'浏览器全局变量'(即通过脚本标记加载* .js文件;所有JS对象是全局变量)移植到AMD样式的模块。

AMD(或CommonJS)的好处之一是依赖注入,其中代码获取本地引用到任何依赖对象,而不是依赖全局引用,例如。

require(['foo'], function(Foo) { 
    var bar = new Foo(); 
}); 

...这使得它很容易做到的对象嘲讽,因为你可以配置模块加载到通过模拟对象为测试模式时,“富”。我希望通过转向依赖注入,我可以解决我的applicationCache问题(因为传递到我的模块中的“窗口”引用可能是全局窗口对象或模拟对象)。

但是我不知道如何require.js注入'窗口'作为依赖到我的模块?

是否有可能(可能使用shim config?)来定义'窗口'模块;然后可以将它传递给在全局“窗口”对象上运行的任何代码?所以我可以这样做:

require(['???'], function(window) { 
    // 'window' here is the real window object, or for testing it's a mock window object 
    window.applicationCache.update(); 
}); 

... where'???'是指窗口对象的模块名称。

或者我需要定义自己的模块,导出“窗口”,它可以不同地映射单元测试,例如。

// 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(); 
}); 

回答

6

我回答了我自己的问题。我决定创建如上所述的window.js和window-mock.js模块,这允许我在运行单元测试时通过模拟版本,并且在正常运行时使用“真实”窗口对象。