Testing JavaScript Modules

October 13, 2015

In our previous post we outlined benefits of writing JavaScript in modules. One benefit we didn’t mention was how much more testable JavaScript modules are. In your test file you can require the module under test and let the require system import any dependencies.

The goal of this post is to outline some of the common testing patterns of JavaScript modules and highlight one of the libraries we have open-sourced to help make testing private state in JavaScript modules even easier.

Public Functions

Below is an example of a utilities file that simply exposes an object with some functions. This is the easiest example of a module to test because all functions are public.

We simply require the file and write tests that the add function works as expected.

Private Functions

Simple Objects

Building on our example from above, here is the same module, but with a private helper function.

When we require the utils module, we can’t access Utils.add. We want to make it visible in the test environment in order to test that function, but not visible to the rest of our code base.

Here at Wealthfront we have built privatestate, a testing library to expose private state of JavaScript modules in our test environment. Below are some examples that outline its benefits. Check out its documentation for more detail!

privatestate lets us expose the private functions like this:

Allowing us to write tests against add.

Functions

Similarly to exposing a function on objects, we can expose helper functions on functions the same way.

Stubbing

Sometimes we want to replace our private state and dependencies when we are in test to help make testing higher level functionality easier. We will use sinon in these examples.

Private Functions

We’ve seen how to properly expose a private function when in a testing environment, but what if we want to stub that function and replace it with something else?

Expose it as we did previously:

And stub it out in our test:

Dependencies

Stubbing dependencies is extremely important for testing JavaScript modules as modules often have multiple dependencies. We use Proxyquire (and its family of related packages).

Proxyquire lets you pass your require call an object of stubs to use instead of module dependencies.

If we are testing utils.js and we want to verify that getString returns helper1.msg, we want to stub out Helper so that we can specify msg. Using Proxyquire, we pass the require statement for Utils our stub for Helper.

Wrapping Up

JavaScript modules help improve the development and test lifecycles by being able to work on standalone modules and expose only the functionality we want depending on the execution environment. While making things only accessible in the module itself is beneficial, it can also make things harder to test. Thankfully privatestate and Proxyquire enable us to test all of those hard-to-reach places.

Go forth and test all of the things!