Testing private JavaScript functions using Babel

Chris Feist
JetClosing Engineering
2 min readSep 18, 2018

--

At JetClosing we utilize decomposition and modular programming. As projects get larger, it’s important to clearly define the interface between objects by exporting the methods that make up that interface. Sometimes this can cause issues when trying to unit test that code, especially the private functions. The existing strategies for accomplishing this have their own issues:

  • Exposing private members - This creates potential security issues and can effect development; such as when auto imports suggest the intended private members over other public members.
  • Testing through public functions - This approach is a pain! In order to have targeted tests for the private functions, it requires a bunch of setup and teardown code just to ensure the private function is executed.
  • Use existing 3rd party options - The current options are limited, and require multiple plugins or custom test imports; such as denude and babel-plugin-test-export.

None of these strategies are ideal or practical in large projects, so we decided to create our own solution as a single Babel plugin: babel-plugin-testable. Like most modern javascript developers, we are using Babel to compile modern javascript into backwards compatible code. Therefore, we made a plugin that could export our ES6+ code for testing purposes.

Integrating the plugin

Install

Install the plugin using your favorite package manager: npm install -D babel-plugin-testable or yarn add -D babel-plugin-testable.

Enable

Add the plugin to your Babel configuration:

Using the Plugin

Now, decorate and import!

Decorate

Add testable comments to the code you want to test:

Import

Import your private members along with the public members in your tests, and add any test code you need:

That’s it!

Now you can import any private function, variable, or class for testing purposes. Simple and clean!

The Nitty Gritty

So how does it work? This is pretty simple too!

When compiling the code, the plugin keys off of the NODE_ENV or BABEL_ENV environment variables to determine if the code is being compiled for tests. If neither of these are 'test', then it compiles as it normally would. Otherwise, it looks for top level private members (variables, functions, and classes) that are annotated with the // @testable comment, and adds an export in front of them. This allows the private members to be imported in your test files like any other exported member.

Give it a shot!

Now that we’ve made testing private members easier for you, give it a shot! Let us know what you think in the comments.

--

--

Chris Feist
JetClosing Engineering

Full stack developer specializing in React and React Native front ends, and AWS backends