Unit testing of private functions with Mocha and Node.js Unit testing of private functions with Mocha and Node.js javascript javascript

Unit testing of private functions with Mocha and Node.js


Check out the rewire module. It allows you to get (and manipulate) private variables and functions within a module.

So in your case the usage would be something like:

var rewire = require('rewire'),    foobar = rewire('./foobar'); // Bring your module in with rewiredescribe("private_foobar1", function() {    // Use the special '__get__' accessor to get your private function.    var private_foobar1 = foobar.__get__('private_foobar1');    it("should do stuff", function(done) {        var stuff = private_foobar1(filter);        should(stuff).be.ok;        should(stuff).....


If the function is not exported by the module, it cannot be called by test code outside the module. That's due to how JavaScript works, and Mocha cannot by itself circumvent this.

In the few instances where I determined that testing a private function is the right thing to do, I've set some environment variable that my module checks to determine whether it is running in a test setup or not. If it runs in the test setup, then it exports additional functions that I can then call during testing.

The word "environment" is loosely used here. It might mean checking process.env or something else that can communicate to the module "you're being tested now". The instances where I've had to do this were in a RequireJS environment, and I've used module.config for this purpose.


Here is a really good workflow to test your private methods explained by Philip Walton, a Google engineer on his blog.

Principle

  • Write your code normally
  • Bind your private methods to the object in a separate code block, and mark it by an _ (for example)
  • Surround that code block by start and end comments

Then use a build task or your own build system (for example grunt-strip-code) to strip this block for production builds.

Your tests builds have access to your private API, and your production builds have not.

Snippet

Write your code as this:

var myModule = (function() {  function foo() {    // Private function `foo` inside closure    return "foo"  }  var api = {    bar: function() {      // Public function `bar` returned from closure      return "bar"    }  }  /* test-code */  api._foo = foo  /* end-test-code */  return api}())

And your Grunt tasks like this:

grunt.registerTask("test", [  "concat",  "jshint",  "jasmine"])grunt.registerTask("deploy", [  "concat",  "strip-code",  "jshint",  "uglify"])

Deeper

In a later article, it explains the "why" of "testing private methods"