How to test functions inside javascript closure

时光总嘲笑我的痴心妄想 提交于 2019-12-12 20:52:27

问题


This seems impossible (and it might be), but I'm trying to get into more TDD and I keep hitting a wall with closures. Say I have the following:

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
    };
}

Putting aside this code probably isn't the best illustration of my point and assuming "privateMethod" is something much more complicated than what is above, is there any way to run unit tests on methods like "privateMethod" or is the best you can do is to test the object created by createSomething? I ask because large parts of my application are hidden inside closures. I'm pretty uninformed in this area, but it seems to me that this is a weak spot for javascript and tdd. fiddle for the code above without tdd is here: http://jsfiddle.net/QXEKd/


回答1:


You can "smuggle" a function (or an Object of functions, variables, etc) out of your closure quite easily by adding an extra parameter to the constructor or hard-coding an early return. The smuggled function should still have the closure from where it was smuggled from unless you're doing something like the evil eval.

It might me worth noting that if you're taking functions out like this for testing purposes only, it may be preferable to comment out or otherwise remove the code to access these before publishing it on your website, so it can't be abused. Also, be aware that this will change depending on how a function is invoked, if you are using it.

For 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



回答2:


Another possibility is to export a function that adds test-cases. It wouldn't export anything that's meant to be out-of-reach (private).

I mostly use Mocha for testing, so I call "describe()" and "it()" from that function that adds tests. For example, let's say I have created a library called "whatever." I could create a function "test" (or _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!");
        });
      });
    }
  };
})();

Then my ./test/tests.js would have:

whatever.test();

One obvious bad point with this is the fact that you can't separate pure code and tests (unless maybe by using some kind of deployment workflow).



来源:https://stackoverflow.com/questions/14159980/how-to-test-functions-inside-javascript-closure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!