在Javascript中模拟window.location.href

wmi*_*ell 64 javascript mocking jasmine

我对一个使用window.location.href的函数进行了一些单元测试 - 不太理想我宁愿通过它,但它在实现中是不可能的.我只是想知道是否有可能模拟这个值而不实际导致我的测试运行器页面实际上转到URL.

  window.location.href = "http://www.website.com?varName=foo";    
  expect(actions.paramToVar(test_Data)).toEqual("bar"); 
Run Code Online (Sandbox Code Playgroud)

我正在使用jasmine作为我的单元测试框架.

Kur*_*ger 50

执行此操作的最佳方法是在某处创建辅助函数,然后模拟:

 var mynamespace = mynamespace || {};
    mynamespace.util = (function() {
      function getWindowLocationHRef() {
          return window.location.href;
      }
      return { 
        getWindowLocationHRef: getWindowLocationHRef
      }
    })();
Run Code Online (Sandbox Code Playgroud)

现在,不要直接在代码中使用window.location.href,而只需使用它.然后,只要需要返回模拟值,就可以替换此方法:

mynamespace.util.getWindowLocationHRef = function() {
  return "http://mockhost/mockingpath" 
};
Run Code Online (Sandbox Code Playgroud)

如果您想要窗口位置的特定部分(例如查询字符串参数),那么也为此创建辅助方法,并保持解析不受主代码的影响.一些框架如jasmine有测试间谍,不仅可以模拟函数返回所需的值,还可以验证它被调用:

spyOn(mynamespace.util, 'getQueryStringParameterByName').andReturn("desc");
//...
expect(mynamespace.util.getQueryStringParameterByName).toHaveBeenCalledWith("sort");
Run Code Online (Sandbox Code Playgroud)


cbu*_*mer 18

我会提出两个解决方案,这些解决方案已在之前的帖子中暗示过:

  • 创建一个围绕访问的函数,在生产代码中使用它,并在测试中使用Jasmine将其存根:

    var actions = {
        getCurrentURL: function () {
            return window.location.href;
        },
        paramToVar: function (testData) {
            ...
            var url = getCurrentURL();
            ...
        }
    };
    // Test
    var urlSpy = spyOn(actions, "getCurrentURL").andReturn("http://my/fake?param");
    expect(actions.paramToVar(test_Data)).toEqual("bar");
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用依赖注入并在测试中注入假冒:

    var _actions = function (window) {
        return {
            paramToVar: function (testData) {
                ...
                var url = window.location.href;
                ...
            }
        };
    };
    var actions = _actions(window);
    // Test
    var fakeWindow = {
       location: { href: "http://my/fake?param" }
    };
    var fakeActions = _actions(fakeWindow);
    expect(fakeActions.paramToVar(test_Data)).toEqual("bar");
    
    Run Code Online (Sandbox Code Playgroud)

  • 在Jasmine 2.x中,第一个示例中使用的语法似乎发生了一些变化.`.andReturn()`应替换为`.and.returnValue()`. (2认同)

And*_*ris 7

您需要模拟当地的情况,并创建自己的版本windowwindow.location对象

var localContext = {
    "window":{
        location:{
            href: "http://www.website.com?varName=foo"
        }
    }
}

// simulated context
with(localContext){
    console.log(window.location.href);
    // http://www.website.com?varName=foo
}

//actual context
console.log(window.location.href);
// http://www.actual.page.url/...
Run Code Online (Sandbox Code Playgroud)

如果你使用with那么所有变量(包括window!)将首先从上下文对象中查找,如果不存在则从实际上下文中查找.

  • 严格模式下不允许使用''with'语句 (23认同)
  • with(obj) {} 语句已弃用,因此在严格模式下无效。 (2认同)
  • “with”到底是什么? (2认同)

Jim*_*acs 5

有时您可能有一个修改window.location的库,并且您希望允许它正常运行但也要进行测试.如果是这种情况,您可以使用闭包将所需的引用传递给您的库,例如这样.

/* in mylib.js */
(function(view){
    view.location.href = "foo";
}(self || window));
Run Code Online (Sandbox Code Playgroud)

然后在测试中,在包含库之前,您可以全局重新定义self,并且库将使用mock self作为视图.

var self = {
   location: { href: location.href }
};
Run Code Online (Sandbox Code Playgroud)

在您的图书馆中,您还可以执行以下操作,因此您可以在测试中的任何位置重新定义自我:

/* in mylib.js */
var mylib = (function(href) {
    function go ( href ) {
       var view = self || window;
       view.location.href = href;
    }
    return {go: go}
}());
Run Code Online (Sandbox Code Playgroud)

在大多数(如果不是全部)现代浏览器中,self默认情况下已经是对窗口的引用.在实现Worker API的平台中,Worker self是对全局范围的引用.在node.js中,self和window都没有定义,所以如果你想要你也可以这样做:

self || window || global
Run Code Online (Sandbox Code Playgroud)

如果node.js确实实现了Worker API,这可能会改变.