在require.js中模拟全局窗口对象

时间:2013-02-25 00:21:08

标签: window mocking requirejs

  1. 我有一个使用window.applicationCache的Web应用程序 离线访问。
  2. 我管理appCache的所有代码 (例如,检查/更新/交换缓存)被封装到一个 “cache-controller”对象。
  3. 我有单元测试来测试我的 “缓存控制器”功能。为了测试,我暂时 用我自己的mock替换本机window.applicationCache对象 版本(因为我只想测试我的代码,而不是浏览器 appCache实现),例如。

    window.applicationCache = { /* my appCache mock */ };
    // unit tests run here. Code under test references window.applicationCache.
    
  4. 不久前(大约是Chrome 16),这种方法非常有效。然后Chrome 17,Mac和Mac Windows平台,删除了通过浏览器的默认window.applicationCache属性进行修补的功能(虽然奇怪的是,它仍适用于Chrome for Linux,适用于所有版本,包括Chrome 26)。当时,我logged a Chromium bug为此;但不幸的是,错误报告仍被列为“未经证实”。

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

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

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

    ...这样可以很容易地进行对象模拟,因为您可以配置模块加载器在测试模式下为'foo'传递模拟对象。

    我曾希望通过转移依赖注入,我可以解决我的applicationCache问题(因为传递给我的模块的'window'引用可以是全局窗口对象,也可以是模拟对象)。

    但是我不确定如何让require.js将'window'作为依赖注入我的模块?

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

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

    ......其中'???'是一个引用窗口对象的模块名称。

    或者我是否需要定义我自己的导出'window'的模块,该模块可以不同地映射单元测试,例如。

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

1 个答案:

答案 0 :(得分:6)

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