17

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?

1

6 Answers 6

9

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.

Sign up to request clarification or add additional context in comments.

5 Comments

Actually, Javascript is not object oriented, it's prototype-based. It just can mimic OO behaviour.
@pcjuzer, Javascript most definitely is object oriented, it's just implemented differently that the classical OO languages most people are familiar with.
How would you add a test public method without losing all security?
@Johnathon based on my research, the best idea is to have some kind of debug flag that allows it. mikeball.us/blog/… I have not used this myself yet.
"If you want to test inner functions you might consider adding a public method for testing purposes only." Eww. Agree with @JohnathonSanders, though s/security/proper factoring/g. (No JavaScript delivered to the user is secure.) The idea is that you are unit testing by calling the public function; you've just split the code into self-commenting (hopefully) private chunks. If you can't test the private function by calling the public and watching mocks, you've got a weird side-effect that's, at best, a serious code smell.
5

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

2 Comments

similar to suggestion here mikeball.us/blog/…
@jlarson url seems to have changed to mikeball.us/blog/testable-private-methods-in-javascript
3

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

Comments

1

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.

1 Comment

This is a problem if you want to unit-test the closure-compiled (or uglified, etc) version. I test only the compiled version - if there's a problem with compilation, I need to know.
0

In an object oriented language, you would typically unit test the protected methods by having the test class inherit from the class it's testing.

Of course, Javascript is not really an object oriented language, and this pattern does not allow for inheritance.

I think you either need to make your methods public, or give up on unit testing them.

3 Comments

In C#, a derived clas cannot access private members of its base class. Is that different with other languages?
In Java also, a private member or method cannot be accessed by subclasses.
Just being pedantic - JavaScript is really object-oriented, but it is not class-based - it is prototype-based.
0

There is the only one right option: Different Builds for Testing and Production

1) mark development only parts

/* test-code */
api._foo = foo
/* end-test-code */

2) strip them later... ;)

grunt.registerTask("deploy", 
  [
    "concat",
    "strip-code",
    ...

@philwalton has written beautiful articles:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.