Skip to content

Instantly share code, notes, and snippets.

@dfkaye
Last active December 19, 2015 12:59
Show Gist options
  • Save dfkaye/5959089 to your computer and use it in GitHub Desktop.
Save dfkaye/5959089 to your computer and use it in GitHub Desktop.
Testing private functionality in JavaScript

Testing private functionality in JavaScript

9 JUL 2013

Start with this example, modified from http://philipwalton.com/articles/how-to-unit-test-private-functions-in-javascript/ by @philwalton

var myModule = (function() {

  function foo() {
    // private function `foo` inside closure
    return "foo"
  }

  return {
    bar: function() {

      // use private foo
      foo()

      // public function `bar` returned from closure
      return "bar"
    }
  }
}())

Testing function bar is straightforward: the call to myModule() should return the string 'bar' in this case.

But how do we test that the internal function foo behaves correctly, given that it is hidden in a closure?

Take the tests for foo and bar in separate stages:

  • Since foo is a dependency for bar, we need to test foo first.
  • Whether or not foo is to be private, we should test foo first as a public api.
  • If foo is to be private, then it shouldn't do too much. That will keep the tests short.
  • However, if foo does a lot, then it shouldn't be private.
  • Once you're satisfied with the foo tests, hide foo in the closure.
  • Then ask, how does bar use foo? just foo(x) or return foo(x)? what gets passed to it? does it get modified?
  • And once you've answered that, you can let or make bar test foo for you.
  • Since you won't need the foo tests anymore, you can move assertions as you need them directly into bar itself and modify as necessary. These would typeof or greater than assertions, or has a property, etc.

The point is, don't get hung up on private anything as something to be mocked. We don't need mocks so much as we good test+dev workflow and ergonomics. That prevents us from overthinking or seeking heroic solutions, and keeps away the anxiety and burnout ~ TDD is meant to do all that.

@dfkaye
Copy link
Author

dfkaye commented Jul 13, 2013

Couple inline comments, too:

Didn't say throw away your tests for a feature when you hide it. You can re-use them in the code that calls the hidden feature.

Also - when private functions do a lot, making changes later gets harder. If the point of testing is to make life easier, why give that back by hiding stuff? And if exposing it temporarily in order to change and test sounds like more work, the only reason it's more work is that it's being hidden away in the first place. "Exactly what battle are you fighting to keep your code more complex?" (Trostler, Testable Javascript, p 25)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment