17

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.

Mike Fielden
  • 10,055
  • 14
  • 59
  • 99
ArtoAle
  • 2,939
  • 1
  • 25
  • 48
  • I don't think you can test it at all, since for that you would need to access the local-scoped variables – Bergi Mar 10 '13 at 12:56
  • You could write a function that will only attach another function to exports if you're actually running tests? – phenomnomnominal Mar 10 '13 at 13:27
  • @phenomnomnominal, you mean something like a function exported only if some 'test' global variable is defined or someting like this? – ArtoAle Mar 10 '13 at 14:16

2 Answers2

24

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.

Golo Roden
  • 140,679
  • 96
  • 298
  • 425
  • 1
    That was what i was thinking (and did for other -more reusable- functions). I don't agree that those may only come from refactoring...does a java private method only come out from refactoring of public ones? I don't think so...anyway, I think the 'move to a module' strategy may be acceptable, I only have doubt about the closure scoping which is lost in favor of dependencies passing, which I'm not sure it's always a good thing – ArtoAle Mar 10 '13 at 18:30
  • If you proceed strictly according to TDD, even in Java every private method will only be the result of a refactoring of one (or more) public methods. But anyway, I guess that's the way to go :-) – Golo Roden Mar 10 '13 at 21:18
  • I wasn't aware of this strict definition :) in this term, I guess you're answer is to considered correct. Can you please point me out some links where to find this kind ok 'statement' about TDD? Thanks – ArtoAle Mar 11 '13 at 17:15
  • I don't have any link at hand to prove it, but if you always code the test first, and you always only implement as much as needed to make the test green, it's quite clear that all you'll end up with is public stuff. With 100% coverage. Private stuff can then only happen from refactoring, but this does not break the 100% coverage rule. – Golo Roden Mar 11 '13 at 19:09
8

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')
Community
  • 1
  • 1
DEADB17
  • 157
  • 2
  • 1
  • Mmm...not really my question :) I mean - I agree that your tool is useful since it separate "public" from "private" exports - but my question was more about how to approach this situation in TDD - I understand that you can monkey-patch everything, I wanted to know if there's a good practice on how to write code and to be honest, explicitly exporting something for the sole purpose of testing is something I don't really like, since I consider TDD more of a guidance on how to write better, more reusable code :) – ArtoAle May 13 '14 at 15:59
  • Best practices, like patterns, depend on the circumstances. The developer still has to consider the trade offs and use judgement. Given that it is valuable to test units of functionality in isolation, to maintain a stable public API and to minimize what is exposed, the library provides an alternative to extracting code into a separate module. e.g.: Wanting to keep related code together or avoiding the risk of other modules starting to depend on the extracted code (it happens in larger teams). So even if the answer is not useful to you now, it might be in the future or to other people. – DEADB17 May 15 '14 at 03:55
  • BTW: there is no monkey-patching involved. The mechanism is the same as regular node exports. – DEADB17 May 15 '14 at 03:59
  • 1
    That's what I said: "your tool is useful" but it doesn't answer my question. If it wasn't of some use I'd have flagged the answer as spam otherwise (since you came back to a very old question, with a reputation of 1, promoting your own library). Btw, what I mean by monkey-patching is that you're creating an alternative environment loading system – ArtoAle May 19 '14 at 23:46