Sinon actually already has a nice API for doing this out of the box without any prototype mucking:
/**
* test.mpsec.js
*/
var sinon = require('sinon');
var expect = require('chai').expect;
var rewire = require('rewire');
var main = rewire('main');
var CoolModuleMock = {
start: sinon.stub().returnsThis(),
end: sinon.stub().returnsThis(),
pause: sinon.stub().returnsThis()
};
I’ll leave my post below for historical purposes, but please just use the code above :)
I’ve recently been writing a lot of unit-tests for some open-source projects, and one of those projects chained method calls to the node rsync
module. I mocked out this dependency, but had to make sinon ‘chainable’ in order to properly test the method calls. It was an interesting thing to implement, so I thought I’d share this bit of code:
/**
* test.mpsec.js
*/
var sinon = require('sinon');
var expect = require('chai').expect;
var rewire = require('rewire');
var main = rewire('main');
var CoolModuleMock = (function() {
function CoolModuleMock() {}
CoolModuleMock.prototype.start = sinon.stub().returns(CoolModuleMock.prototype);
CoolModuleMock.prototype.pause = sinon.stub().returns(CoolModuleMock.prototype);
CoolModuleMock.prototype.end = sinon.stub().returns(CoolModuleMock.prototype);
return CoolModuleMock;
})();
// Overwrite the `CoolModule` reference to refer to our mock
main.set__('CoolModule', CoolModuleMock);
describe('Cool Module', function() {
it('should call the `start`, `pause`, and `end` methods', function() {
main();
expect(CoolModuleMock.start.called).to.be.true();
expect(CoolModuleMock.pause.called).to.be.true();
expect(CoolModuleMock.end.called).to.be.true();
});
});
/**
* main.js
*/
var CoolModule = require('cool-module'); // rewire will overwrite this
var cool = new CoolModule();
module.exports = function() {
cool.start();
cool.pause();
cool.end();
};