测试使用闭包变量的Javascript函数的最佳方法?

时间:2012-02-13 03:08:33

标签: javascript closures qunit

所以我遇到的问题是我有一个在闭包中使用变量的函数,在测试它时会返回对其范围内变量的引用。我的代码类似于以下内容:

var app = function() {
    var theString = "";

    //Appends ztvars onto the url passed into the function
    var appendString = function(url) {            
        if (theString.length === 0) {
            return url;
        }

        return url+theString;   
    };

    //Used for testing, returns the function appendPageVars
    this.returnFunctions = function() {
        return { appendString: appendString };
    }
}

使用QUnit的测试代码如下所示:

var theApp = new app();
appFunctions = theApp.returnFunctions();
test('appendString()', function() {
    var theString = "TestString";
    var theUrl = "http://www.test.com";
    equals(appFunctions.appendString(testUrl), theUrl+theString, "Checking the string appended to the url"); //Fails
});

问题在于,即使将函数传递回测试,appendString函数仍然保存对应用程序范围内定义的theString的引用。

我设法通过使用eval创建函数的克隆而不是直接使用它来解决这个问题:

var theApp = new app();
appFunctions = theApp.returnFunctions();
test('appendString()', function() {
    var theString = "TestString";
    var theUrl = "http://www.test.com";
    eval("var appendString = "+appFunctions.appendString.toString());
    equals(appendString(testUrl), theUrl+theString, "Checking the string appended to the url"); //Passes
});

然而,我一直被教导要避免评估,所以我想知道有更好的方法吗?我在这里遗漏了什么,或者这是应该怎么做的?

2 个答案:

答案 0 :(得分:0)

当您为对象提供模拟对象时,您需要的是依赖注入。

var App = function (theString) {
  theString = theString || ''; // optional argument

  var appendString = function (str) {
    return theString + str;
  };
  this.returnFunctions = function () {
    return { appendString: appendString };
  };
};

test('appendString()', function () {
  var app = new App('TestString');
  var fns = app.returnFunctions();
  equals(fns.appendString('test'), 'TestStringtest', ...);
});

答案 1 :(得分:0)

据我所知,答案是使用Eval重新创建函数(根据我的例子)。虽然在这种情况下教导eval被避免,但它似乎是正确的做法。谢谢大家的帮助!