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!