Please familiarise yourself with why we have ES6 Modules and its terminology as it going to help you to understand some of the issues we will be discussing here. The article, An Introduction To JavaScript ES6 Modules is a good place to start.

We can write perfectly functioning code, that is simple, readable and optimised. But when it comes to testing, it adds another dimension to your code and changes the way you would approach coding. Those who have developed in C#, you know why we need Interfaces and implementing it will change the way you approach writing your code.

The following issues are known pain points when it comes to testing ES6 modules:

  • Named Exports
  • Multiple Exports

We will use a Warehouse example, which uses Mocha, Sinon and Chai, to explore how we can rewrite the code to get them to pass the above mentioned pain points, and still have them function properly. Although the title mentions spying, the idea is that if you can Spy then you should be able to Stub and Mock.

Setting the Scene

The following snippet is our warehouseManager.js. You can increase the stock count of a particular stock and save it to a store via warehouseRepository.js.

warehouseManager snippet.PNG

The following snippet shows the implementation of the repository, which isn’t that exciting.


Named Exports

The SUT is updateStockCount(). When we run the following test we find that it actually fails. What would your wild guess be?

Named Export - Fail.PNG

If it had anything to do with the import statement then you are pretty close. But lets ask the right question. What is Sinon spying on?

Sinon is spying on the variable updateStockCount that contains the exported function updateStockCount from warehouseManager.js.

Let’s analyse that statement a bit further. The function updateStockCount was exported into the variable called updateStockCount and Sinon is setup to spy on the variable rather than the actual function on that file. The following snippet behaves exactly the same, except for the fact that it uses an alias to export the function into. Hopefully this will clarify the issue a bit further.

Named Export - Fail 2.PNG

Given we do not want to spy on a variable but rather that the a function. To do that we need to treat it like a module and import warehouseManager.js into as an object and then spy its functions. Given it is now being treated as an object, the Spy syntax changes a little bit. The following snippet shows how we can test it correctly.

Named Export - Pass.PNG

Multiple Exports

The following test is trying to verify that when update the count of a stock that the getLastUpdateDate function was called.

Multiple Exports - Fail.PNG

Although the test reads well and should be passing, it unfortunately doesn’t.

The reason for it is because the getLastUpdateDate method that updateStockCount calls is in the local context and not the exported context.

What this means is that getLastUpdateDate is referring to updateStockCount as an internal function that outside world cannot inspect or know about Our test is spying on the the exported context, which is why we see that the call was never made. So how do we go about fixing this?

We can fix this by updating the warehouseManager.js to export a single module with multiple functions rather than exporting multiple functions.

Multiple Exports - Pass 1.PNG

This change isn’t going to pass the test immediately, actually it will be breaking the test. The test isn’t aware that warehouseManager.js has default export, so we need to modify the import to reflect this change.



Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s