Select Page

When testing Node modules, one of the challenges you face is dealing with other module dependencies (either third-party modules or your own ones). Let’s say you want to test this module:

var electricSaw = require("./electricSaw"),
    table = {
        wood: {}
    };

function makeTable() {
    electricSaw.cut(table.wood);
    table.finished = true;
    return table;
}

module.exports = {
    makeTable: makeTable
};

Notice electricSaw is an external module being referenced by the module you want to test. How can you deal with it?

  1. You could not worry about it and test the whole thing in its entirety. This could be useful in some situations (e.g., acceptance testing), but not so much in others (e.g., unit testing). It depends on what your end goal is.
  2. If your goal is to isolate your module, then you’ll need to somehow figure out how to inject a test double instead of the actual electricSaw module.

If you decide to use test doubles, you have mainly 2 options: either replace Node’s require function yourself (which requires you to know more about Node’s internals), or rely on existing modules like rewire, proxyquire, or SandboxedModule. Let’s look at how we can leverage rewire, along with mocha (test framework), sinon (for mocking) and should (for BDD-style assertions) to accomplish this:

var should = require("should"),
    sinon = require("sinon"),
    rewire = require("rewire");

describe("A carpenter", function() {
    var carpenter = rewire("./carpenter"),
        electricSaw = {
            cut: sinon.spy()
        };

    describe("when using an electric saw", function() {
        before(function() {
            carpenter.__set__("electricSaw", electricSaw);
        });

        it("should be able to make a table", function() {
            var table = carpenter.makeTable();

            electricSaw.cut.calledOnce.should.be.true;
            electricSaw.cut.calledWith({}).should.be.true;
            table.finished.should.be.true;
        });
    });
});

The most important concept in this snippet is the use of rewire, instead of require to import your module. This will allow you to replace the dependencies with your own test doubles (via rewire’s __set__ function). This is the main key to enabling this whole mocking approach. Eventually, as the complexity of your code-under-testing grows, you’ll also need to get skilled with different mocking concepts.

Here’s a github project I use to play with this Node mocking approach.