是否可以模拟window.location对象进行qUnit测试?

jba*_*bey 18 javascript unit-testing qunit query-string

假设我有一个实用函数,为了简单起见(真实的东西很复杂且无关紧要),返回当前窗口的查询字符串.

var someUtilityFunction = () {
    return window.location.search.substring(1);
};
Run Code Online (Sandbox Code Playgroud)

现在我想在qUnit中对这个函数进行单元测试(不确定测试工具是否相关):

test('#1 someUtilityFunction works', function () {
    // setup
    var oldQS = window.location.search;
    window.location.search = '?key1=value1&key2=value2&key3=value3';

    var expectedOutput = 'key1=value1&key2=value2&key3=value3';

    // test
    equals(someUtilityFunction(),
        expectedOutput,
        'someUtilityFunction works as expected.');

    // teardown
    window.location.search = oldQS;
});
Run Code Online (Sandbox Code Playgroud)

这里的问题是设置window.location.search为不同的查询字符串会导致页面重新加载,实质上是进入无限的请求循环.有没有办法模拟window.location对象而不someUtilityFunction函数进行任何更改?

Tor*_*ter 19

我们几天前遇到了同样的问题.主要有两种方法:

重写你的代码

这可能不是最好的(如果有的话)解决方案,但考虑将window对象传递给您的函数以使模拟更容易.更好的是,使用闭包并封装您的代码.这有几个优点:

  • 你可以影响全球变量
  • 您可以使用私人本地变量
  • 您可以避免命名冲突
  • 阴影使得模拟非常简单,只需传递其他内容

包裹你的代码

您可以将所有代码包装在将窗口对象模拟为局部变量的函数中.你基本上有两种可能性:

假设这是模拟:

var customWindow = {
    location: {
        search: "",
        hash: ""
    }
};
Run Code Online (Sandbox Code Playgroud)

使用封闭物

var someUtilityFunction;

(function(window) {
    // window is now shadowed by your local variable
    someUtilityFunction = () {
        return window.location.search.substring(1);
    };
})(customWindow);
Run Code Online (Sandbox Code Playgroud)

这会影响全球window的本地化window.

使用该with声明

虽然我经常强烈反对,但它可以解决很多问题.由于它基本上重新映射了您的范围,因此您可以轻松地模拟您的环境.

// first some more preparation for our mock
customWindow.window = customWindow;

with(customWindow) {

    // this still creates the var in the global scope
    var someUtilityFunction = () {
        // window is a property of customWindow
        return window.location.search.substring(1);
    };

    // since customWindow is our scope now
    // this will work also
    someUtilityFunction = () {
        // location is a property of customWindow too
        return location.search.substring(1);
    };

}
Run Code Online (Sandbox Code Playgroud)

顺便说一句:我不知道该search财产是否有与财产相同的症状hash- 有时包括问号,有时不包括.但是你可能想考虑使用

window.location.search.replace(/^\?/, "");
Run Code Online (Sandbox Code Playgroud)

代替

window.location.substr(1);
Run Code Online (Sandbox Code Playgroud)