-->

How to unit test 'private' utility functio

2019-03-18 02:29发布

问题:

I'm currently writing some tests for a nodejs application. assume that I have a module like this:

module.exports = function myModule(moduleParam) {
    var someVar;
    ....
    ....
    function helper(param) {
        return param + someVar;
    }
    return {
        doSomething: function (bar) {
            ....
            ....
            var foo = helper(bar);
            ....
            ....
        }
    };
};

Assume that the 'helper' function is useful only within the module and should not be exposed to the outside.

What is the 'best practice' for testing it? (of course, I can test the doSomething function as a whole,but this way, the 'helper' function is tested in a particular situation, in a 'black-box' fashion).

I'm using nodeunit as testing framework, for that metter, but I can change it on need.

回答1:

You don't test it. Unit testing is black box testing. This means that the only thing you test is the public interface aka contract.

Private functions such as these only can happen from refactoring public ones.

So if you consequently use TDD your private functions are implicitly tested.

If this feels wrong it's most often because your structure is wrong. Then you should think about moving your private stuff to an extra module.



回答2:

Since i find tests to be a useful tool beyond unit testing and TDD (this SO answer makes a good argument), I made an npm package to help in cases like yours: require-from.

In you example this is how you would use it:

module-file.js:

function helper(param) {
    return param + someVar;
}

module.exports = function myModule(moduleParam) {
    var someVar;
    ....
    ....
    return {
        doSomething: function (bar) {
            ....
            ....
            var foo = helper(bar);
            ....
            ....
        }
    };
};
module.helperExports = helper;

importing-file.js:

var requireFrom = require('require-from');
var helper = requireFrom('helperExports', './module-file'));
var public = requireFrom('exports', './module-file')); // same as require('./module-file')