What is rewire?
Rewire is a testing utility for Node.js that allows you to modify the behavior of a module by overriding its private variables and functions. This is particularly useful for unit testing, as it enables you to test private functions and mock dependencies.
What are rewire's main functionalities?
Accessing Private Variables
This feature allows you to access private variables within a module. In the code sample, `privateVar` is a private variable in `myModule` that is accessed using `__get__`.
const rewire = require('rewire');
const myModule = rewire('./myModule');
const privateVar = myModule.__get__('privateVar');
console.log(privateVar);
Mocking Private Functions
This feature allows you to mock private functions within a module. In the code sample, `privateFunction` is a private function in `myModule` that is mocked using `__set__`.
const rewire = require('rewire');
const myModule = rewire('./myModule');
myModule.__set__('privateFunction', function() { return 'mocked'; });
console.log(myModule.somePublicFunction());
Mocking Dependencies
This feature allows you to mock dependencies of a module. In the code sample, `dependency` is a dependency of `myModule` that is mocked using `__set__`.
const rewire = require('rewire');
const myModule = rewire('./myModule');
myModule.__set__('dependency', { someMethod: () => 'mocked' });
console.log(myModule.somePublicFunction());
Other packages similar to rewire
proxyquire
Proxyquire is a module that allows you to override dependencies during testing. Unlike Rewire, which focuses on accessing and modifying private variables and functions, Proxyquire is more about replacing entire dependencies with mocks or stubs.
sinon
Sinon is a testing library that provides standalone test spies, stubs, and mocks. While it doesn't allow you to access private variables directly like Rewire, it is very powerful for creating mocks and stubs for functions and objects.
testdouble
Testdouble is a library for creating test doubles (mocks, stubs, etc.). It focuses on providing a clean and simple API for creating test doubles, but it doesn't provide the ability to access or modify private variables like Rewire.
rewire
Dependency injection for node.js applications.
rewire adds a special setter and getter to modules so you can modify their behaviour for better unit testing. You may
- inject mocks for other modules
- leak private variables
- override variables within the module.
rewire does not load the file and eval the contents to emulate node's require mechanism. In fact it uses node's own require to load the module. Thus your module behaves exactly the same in your test environment as under regular circumstances (except your modifications).
Furthermore rewire comes also with support for various client-side bundlers (see below).
Dependency tracking by David
Installation
npm install rewire
Examples
Imagine you want to test this module:
var fs = require("fs"),
http = require("http"),
someOtherVar = "hi",
myPrivateVar = 1;
function readSomethingFromFileSystem(cb) {
var path = "/somewhere/on/the/disk";
console.log("Reading from file system ...");
fs.readFile(path, "utf8", cb);
}
exports.readSomethingFromFileSystem = readSomethingFromFileSystem;
Now within your test module:
var rewire = require("rewire");
var myModule = rewire("../lib/myModule.js");
myModule.__set__("myPrivateVar", 123);
myModule.__get__("myPrivateVar");
myModule.__set__("fs", {
readFile: function (path, encoding, cb) {
cb(null, "Success!");
}
});
myModule.readSomethingFromFileSystem(function (err, data) {
console.log(data);
});
myModule.__set__({
fs: fsMock,
http: httpMock,
someOtherVar: "hello"
});
myModule.__set__({
console: {
log: function () { }
},
process: {
argv: ["testArg1", "testArg2"]
}
});
myModule.__set__("console.log", function () { });
rewire("./myModule.js") === rewire("./myModule.js");
##API
###rewire(filename): rewiredModule
- filename:
Path to the module that shall be rewired. Use it exactly like require().
###rewiredModule.__set__(name, value)
- name:
Name of the variable to set. The variable should be global or defined with var
in the top-leve scope of the module. - value:
The value to set.
###rewiredModule.__set__(env)
- env:
Takes all keys as variable names and sets the values respectively.
###rewiredModule.__get__(name): value
Returns the private variable.
##Client-Side Bundlers
Since rewire relies heavily on node's require mechanism it can't be used on the client-side without adding special middleware to the bundling process. Currently supported bundlers are:
Please note: Unfortunately the line numbers in stack traces have an offset of +2 (browserify) / +1 (webpack).
This is caused by generated code that is added during the bundling process.
###browserify
var b = browserify(),
bundleSrc;
b.use(require("rewire").bundlers.browserify);
b.addEntry("entry.js");
bundleSrc = b.bundle();
###webpack
rewire doesn't run with webpack 0.9 because of various breaking api changes. I'm working on that.
var webpackOptions = {
output: "bundle.js"
};
require("rewire").bundlers.webpack(webpackOptions);
webpack("entry.js", webpackOptions, function () {});