如何测试javascript闭包内的函数

时间:2013-01-04 15:28:19

标签: javascript tdd closures

这似乎是不可能的(也可能是这样),但是我正试图进入更多的TDD,并且我一直在打开带有闭合的墙。说我有以下内容:

function createSomething(init) {
    function privateMethod(param) {
        return init[param];  //assuming this is more complicated, how can you test it?
    }

    function getData() {
        return init.data;
    }

    function getValue(name) {
        if (name === "privateNode" || typeof name !== "string") {
            return "permissionDenied";
        }
        return privateMethod(name);
    }

    return {
        getData : getData,
        getValue: getValue
    };
}

抛开这段代码可能不是我的观点的最佳说明,并假设“privateMethod”比上面的内容复杂得多,有没有办法在像“privateMethod”这样的方法上运行单元测试,或者是最好的你能做的是测试createSomething创建的对象吗?我问,因为我的应用程序的大部分都隐藏在闭包内。我在这方面很不知情,但在我看来,这是javascript和tdd的弱点。 上面没有tdd的代码的小提琴就在这里:http://jsfiddle.net/QXEKd/

2 个答案:

答案 0 :(得分:3)

您可以通过adding an extra parameter to the constructor或者对早期返回进行硬编码,轻松地将函数(或函数,变量等的对象)“偷运”出关闭。走私的功能仍然应该从走私的地方进行封闭,除非你做的是邪恶的eval

我可能值得注意的是,如果您仅仅为了测试目的而将这样的功能用于此类,则可能最好在将其发布到您的网站之前注释掉或以其他方式删除代码以访问这些功能,因此它不能被虐待另外,请注意this将根据函数的调用方式而改变,如果您正在使用它。

example

function createSomething(init, aaa) {
    function privateMethod(param) {
        return init[param];  //assuming this is more complicated, how can you test it?
    }

    function getData() {
        return init.data;
    }

    function getValue(name) {
        if (name === "privateNode" || typeof name !== "string") {
            return "permissionDenied";
        }
        return privateMethod(name);
    }
    // ----------------------------------
    if(aaa) return privateMethod;
    // ----------------------------------
    return {
        getData : getData,
        getValue: getValue
    };
}

var something = createSomething({
    privateNode : "allmysecrets",
    id : "1234",
    data : {
        stuff : "32t97gfhw3hg4"
    }
}, 1); // passing extra arg to get method

console.log(
    something('id'),
    something('privateNode')
) // 1234 allmysecrets

答案 1 :(得分:0)

另一种可能性是导出添加测试用例的函数。它不会导出任何意味着不可及的(私人)。

我主要使用Mocha进行测试,因此我从添加测试的函数中调用“describe()”和“it()”。例如,假设我创建了一个名为“whatever”的库。我可以创建一个函数“test”(或_test,_addTests,...):

var whatever = (function() {
  var insideClosure = "Ha ha!";
  return {

    // obviously you would have other functions too
    test: function() {
      describe('something', function() {
        it('should work', function() {
          assert.equal(insideClosure, "Ha ha!");
        });
      });
    }
  };
})();

然后我的./test/tests.js会:

whatever.test();

这有一个明显的坏处是您无法分离纯代码和测试(除非可能使用某种部署工作流程)。