How to test private functions of CommonJs module

Maciej Sikora
3 min readOct 24, 2017

--

CommonJs modules give great feature, local scope of variables and functions. This feature helps to encapsulate private resources and block access to them from outside. How to, in this circumstances test such functions hidden inside a module, do we really need to export them all in order to manage unit tests, even though it will break the private scope? Or maybe let’s test only public api of the module?

I will start from the second idea — test only public api. In my opinion it is wrong for many reasons, first of all in tdd (test driven development) tests are first, or should be written in the same time. If private methods are not tested, indeed it means that those functions weren’t created in tdd way. In the result it is harder to write single responsibility functions inside the module due to lack of a way to check them as an single units.

Creating functions without testing

Second possible option — give everything you got there. Export all private resources to have access to them in tests.

Answer for that is simple — No, don’t do that. Don’t export private functions outside the module. Don’t, because the module will loose very crucial attribute — public api which should be smart and contain only functions prepared to be public and planned for the outside use.

Export everything vs export smart

How then eat the cake and have the cake? With the help comes rewire (https://github.com/jhnns/rewire). It is a library created to solve such problems. It gives a possibility to read module and extract private resources in due to use them while testing.

How to use it then. Let’s take example module.

Example user.js module has inside four private functions and one public. In order to have efficient and useful module let’s export only single public function, others are left as local scope functions.

Great, now it is module with encapsulated functions, and clearly extracted public api. How test it then?

This is full test file, with fully covered functions from private and public scope of the user module. Most important in this code snippet are lines from 4 to 12.

// standard using of exported functions
const { createUser } = require('./user')
// using rewire to get into private
const userRewire = rewire('./user')
const hasProp = userRewire.__get__('hasProp')
const hasProps = userRewire.__get__('hasProps')
const isString = userRewire.__get__('isString')
const arePropsStrings = userRewire.__get__('arePropsStrings')

In those lines the single public function is taken directly from module (createUser), but other functions are here thanks to rewire library. It gives direct access to private resources by __get__ function.

All things considered, it looks like you can have a cake and eat it too, and it is clearly possible by using rewire. Rewire allows to test private scope without any code refactoring and most importantly without choosing the lesser of two evils.

--

--