NodeJS and Javascript (requirejs) dependency injection NodeJS and Javascript (requirejs) dependency injection express express

NodeJS and Javascript (requirejs) dependency injection


I've come up with a solution for dependency injection. It's called injectr, and it uses node's vm library and replaces the default functionality of require when including a file.

So in your tests, instead of require('libToTest'), use injectr('libToTest' { 'libToMock' : myMock });. I wanted to make the interface as straightforward as possible, with no need to alter the code being tested. I think it works quite well.

It's just worth noting that injectr files are relative to the working directory, unlike require which is relative to the current file, but that shouldn't matter because it's only used in tests.


I've previously toyed with the idea of providing an alternate require to make a form of dependency injection available in Node.js.

Module code

For example, suppose you have following statements in code.js: fs = require('fs');

console.log(fs.readFileSync('text.txt', 'utf-8'));

If you run this code with node code.js, then it will print out the contents of text.txt.

Injector code

However, suppose you have a test module that wants to abstract away the file system.
Your test file test.js could then look like this:

var origRequire = global.require;global.require = dependencyLookup;require('./code.js');function dependencyLookup (file) {  switch (file) {    case 'fs': return { readFileSync: function () { return "test contents"; } };    default: return origRequire(file);  }}

If you now run node test.js, it will print out "test contents", even though it includes code.js.


I've also written a module to accomplish this, it's called rewire. Just use npm install rewire and then:

var rewire = require("rewire"),    myModule = rewire("./path/to/myModule.js"); // exactly like require()// Your module will now export a special setter and getter for private variables.myModule.__set__("myPrivateVar", 123);myModule.__get__("myPrivateVar"); // = 123// This allows you to mock almost everything within the module e.g. the fs-module.// Just pass the variable name as first parameter and your mock as second.myModule.__set__("fs", {    readFile: function (path, encoding, cb) {        cb(null, "Success!");    }});myModule.readSomethingFromFileSystem(function (err, data) {    console.log(data); // = Success!});

I've been inspired by Nathan MacInnes's injectr but used a different approach. I don't use vm to eval the test-module, in fact I use node's own require. This way your module behaves exactly like using require() (except your modifications). Also debugging is fully supported.