Helpful Node.js testing utilities
Tags: node
Published: 2020-04-15 21:18:27

This is not a post about Node.js' testing frameworks, assertion libraries or mocking libraries like Jest, Chai, Mocha and Sinon. This is a short list of libraries that provide functionality that has helped me set up an effective test environment.

## [Decache](https://www.npmjs.com/package/decache)

This is my number 1 tool when testing a library I'm building that stores global state. Here's what their readme says:

> In node.js when you require\(\) a module, node stores a cached version of the module, so that all subsequent calls to require\(\) do not have to reload the module from the filesystem. decache \( Delete Cache \) lets you delete modules from node.js require\(\) cache

[I used decache in my event management library, Burns](https://github.com/shalvah/burns/blob/master/test/tests/burns.js#L17). I use it to restore the state of the module being tested in an `afterEach` hook. This is especially important as Burns keeps track of global state.

## [Mitm](https://www.npmjs.com/package/mitm)

Mitm is a package for intercepting network calls \(TCP or HTTP\) dispatched from your code. I 've used mitm to [fake responses from the Twitter API](https://github.com/shalvah/RemindMeOfThisTweet/blob/master/spec/support/mocks.js#L27) in my Twitter reminders bot, [@RemindMe\_OfThis](https://twitter.com/RemindMe_OfThis). It allows me to basically do whatever I like, such as recording the requests and responding differently depending on the request data.

## [mock\-require](https://www.npmjs.com/package/mock-require)

mock\-require allows you override `require` calls by specifying what should be returned when a particular module is returned. \[I used it multiple times in @RemindMe\_OfThis\] \([https://github.com/shalvah/RemindMeOfThisTweet/blob/master/spec/support/mocks.js](https://github.com/shalvah/RemindMeOfThisTweet/blob/master/spec/support/mocks.js)\) to return my own fakes for dependencies my code needed.

Now, some folks would probably say I should have used dependency injection instead, in which case I could easily inject my mocks without having to use `mock-require` or hack Node.js' module system. They're probably right. However, in my experience, it's been quite painful \(and overkill\) implementing DI in Node.js \(especially when there's no static typing\). I prefer to stick with the straightforward approach—the module system.😀

Some alternatives to mock\-require:

* [`rewire`](https://www.npmjs.com/package/rewire): This does a similar job, and more, but you have to replace your `require` call with `rewire` and then manually specify the mocks. One advantage of that is that you're only mocking for that instance, not globally. This didn't fit my use case, though.
* [`proxyquire`](https://www.npmjs.com/package/proxyquire): Similar to `rewire`, it replaces `require()` and lets you override on a per\-instance basis, but with a simpler API.

## [`MockDate`](https://www.npmjs.com/package/mockdate)

This is a very specific utility, one that will only come in handy if you're working with dates/times and need to have control over the time exposed to your code. It's quite simple to use—you just need to call `require('mockdate').set(date)` and whenever you call `new Date()`, you'll get that date. One important caveat is that you can't change the timezone, though—Node.js [doesn't let you do that easily](https://stackoverflow.com/questions/8083410/how-can-i-set-the-default-timezone-in-node-js) \(until version 13\).

## [`redis-mock`](https://www.npmjs.com/package/redis-mock)

This is an even more specific package—it's a mock of [`node-redis`](https://www.npmjs.com/package/redis). The idea is to give you a fake datastore so that your code continues to think it's talking to a live Redis server, but it's really talking to an in\-memory object managed by `redis-mock`. [I used it](https://github.com/shalvah/DownloadThisVideo/blob/master/spec/support/mocks.js#L5) \(in combination with mock\-require\) in my Twitter video downloader bot, [@this\_vid](https://twitter.com/this_vid) to fake the bot's datastore. The cache can be easily reset for each test by flushing it like you would a real cache in a \([`beforeEach`/`afterEach` hook](https://github.com/shalvah/DownloadThisVideo/blob/master/spec/sendDownloadLink.spec.js#L19)\)

I love most of these tools because of how "drop\-in" they are, allowing me to "pretend" to use the actual objects . Many of them may not conform to some strict ideas about testing and mocking, but I like them because they're simple and allow me to focus on testing my application logic rather than setting up some unnecessarily complicated architecture.