sinon vs rewire: when do I use which?

In node.js testing, there are 2 helper modules that I use often: sinon and rewire. Sinon allows you to monkey-patch functions, while rewire allows you to… monkey-patch functions. Both modules have other uses as well, but in this post I’m focusing on monkey-patching.

So, in which situations should you use sinon and when should you use rewire for monkey-patching?

In short: if you are testing module A, and inside module A there is a call to a function of module B, you should use sinon. If you want to monkey-patch a call to a function inside module A itself, you should use rewire (and optionally, sinon as well).

Here is an example.

In your test file, when you are testing testMe , you can mock b.b1  by doing this:

This works, because in node.js, each require() ‘ed module is a singleton. So the b  in your test file is the same as the b  in a.js . Therefore, sinon can overwrite the b.b1  function in the test file, which results in the call to b.b1  inside testMe  ending up in sinon’s mock.

Unfortunately, this doesn’t work for the a1  call. This function is not exported by a.js , and even if it was, overwriting it with sinon would not have any effect. The reason for this, is that a1 is called “directly” from testMe.

One way to work around this, is to modify the source code in the following way.

In your test file, you can now require('./a')  and use sinon to mock a.a1() . Ugh. This is not elegant at all.

Fortunately, rewire allows us to overwrite even private functions. All you need to do in your test file is the following:

This is a bit more work, but at least you don’t need to change the source code.

This entry was posted in JavaScript, node.js, software development, testing and tagged , , , , , , , . Bookmark the permalink.

One Response to sinon vs rewire: when do I use which?

  1. David Schile says:

    You have an error in the first block of code in this demo (a.js).
    you export test, but there is no test. You named the function testMe

Leave a Reply

Your email address will not be published.