javascriptprototypemocha.jssinonstubs

Stubbing a prototype method with sinon


Let's say I have the following methods:

Controller.prototype.refresh = function () {
  console.log('refreshing');
}

Controller.prototype.delete = function (object) {
  var self = this;
  object.delete({id: object.id}, function () {
    self.refresh();
  });
}

now in my (mocha) test:

beforeEach(function () {
  var controller = new Controller();
  var proto = controller.__proto__;
  var object = {id: 1, delete: function (options, callback) { callback (); };
  sinon.stub(proto, 'refresh', function {console.log('refreshing stub')});
  controller.delete(object);
});

it('doesnt work', function () {
  expect(object.delete.callCount).to.equal(1);
  expect(proto.refresh.callCount).to.equal(1);
});

This, however, prints "refreshing" to the console. Is there a way to use sinon to stub a live prototype?


Solution

  • This is how I would do it:

    describe('test', function() {
      before(function() {
        // stub the prototype's `refresh` method
        sinon.stub(Controller.prototype, 'refresh');
        this.object = {
          id: 1,
          delete: function (options, callback) { callback (); }
        };
        // spy on the object's `delete` method
        sinon.spy(this.object, 'delete');
      });
    
      beforeEach(function () {
        // do your thing ...
        this.controller = new Controller();
        this.controller.delete(this.object);
      });
    
      after(function() {
        // restore stubs/spies after I'm done
        Controller.prototype.refresh.restore();
        this.object.delete.restore();
      });
    
      it('doesnt work', function () {
        expect(this.object.delete.callCount).to.equal(1);
        expect(this.controller.refresh.callCount).to.equal(1);
      });
    });