unit-testing jest - Testing private functions in javascript





nodejs inner (6)


My solution is just a little bit of hack. QUnit example:

At the top of Qunit test html I have declared:

var TEST_AVAILABLE = true;

In the testable class I have a fragment like this:

if(TEST_AVAILABLE){
   this.test={
      hasDraft:hasDraft,
      isInterpIdIn:isInterpIdIn,
      // other private methods
   };
}

In the QUnit you could verify

test( "hello booth", function() {
  var b = new Booth();
  ok(b);
  ok(b.test);
  ok(!b.test.hasDraft());
});

I'm using the module pattern in Javascript to separate my public interface from the private implementation. To simplify what I'm doing, my code generates a chart. The chart consists of multiple parts (axises, labels, plot, legend, etc.) My code looks like:

var Graph = function() {
  var private_data;
  function draw_legend() { ... }
  function draw_plot() { ... }
  function helper_func() { ... }
  ...

  return {
    add_data: function(data) {
      private_data = data;
    },
    draw: function() {
      draw_legend()
      draw_plot()
    }
  }
}

Some people advocate only testing the public interface of your classes, which makes sense, but I'd really like to get in some tests to test each of the components separately. If I screw up my draw_legend() function, I'd like that test to fail, not a test for the public draw() function. Am I on the wrong track here?

I could separate each of the components in different classes, for example make a Legend class. But it seems silly to create a class for what's sometimes just 5-10 lines of code, and it would be uglier because I'd need to pass in a bunch of private state. And I wouldn't be able to test my helper functions. Should I do this anyway? Should I suck it up and only test the public draw()? Or is there some other solution?




There is no way to access inner functions (private) from an outer scope. If you want to test inner functions you might consider adding a public method for testing purposes only. If you are using some sort of a build environment, for example ant, you may pre-process the javascript file for production and remove those test functions.

Actually Javascript is an Object oriented language. It's just not a statitcally typed one.




I have a similar problem. The solution I came up with is not something I like but it does the job and there's not a better solution I can find.

function Graph()
{
    this.Test = function _Test(expressionStr) { return eval(expressionStr); }

    var private_data;
    function draw_legend() { ... }
    function draw_plot() { ... }
    function helper_func() { ... }
    ...
}

To test:

var g = new Graph();
g.Test("helper_func()") == something;
g.Test("private_data") == something2






There is an easy way actually. You can use ajax to load the script and inject a function that exposes the private functions. I have an example here that uses qUnit and jQuery. But I'm sure the same can be easily accomplished using pure Javascript.




My usual method is:

var require = function (src, cb) {
    cb = cb || function () {};

    var newScriptTag = document.createElement('script'),
        firstScriptTag = document.getElementsByTagName('script')[0];
    newScriptTag.src = src;
    newScriptTag.async = true;
    newScriptTag.onload = newScriptTag.onreadystatechange = function () {
        (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') && (cb());
    };
    firstScriptTag.parentNode.insertBefore(newScriptTag, firstScriptTag);
}

It works great and uses no page-reloads for me. I've tried the AJAX method (one of the other answers) but it doesn't seem to work as nicely for me.

Here's an explanation of how the code works for those that are curious: essentially, it creates a new script tag (after the first one) of the URL. It sets it to asynchronous mode so it doesn't block the rest of the code, but calls a callback when the readyState (the state of the content to be loaded) changes to 'loaded'.







javascript unit-testing