Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 371
Abraham P Avatar asked Dec 15 '14 12:12

Abraham P


People also ask

How do you stub a method in Sinon?

var stub = sinon. stub(obj); Stubs all the object's methods. Note that it's usually better practice to stub individual methods, particularly on objects that you don't understand or control all the methods for (e.g. library dependencies).

How does Sinon stub work?

The sinon. stub() substitutes the real function and returns a stub object that you can configure using methods like callsFake() . Stubs also have a callCount property that tells you how many times the stub was called. For example, the below code stubs out axios.

What is stubbing in JavaScript?

What are Stubs? A test stub is a function or object that replaces the actual behavior of a module with a fixed response. The stub can only return the fixed response it was programmed to return.

What does sandbox stub do?

sandbox.Causes all stubs and mocks created from the sandbox to return promises using a specific Promise library instead of the global one when using stub. rejects or stub. resolves . Returns the stub to allow chaining.


1 Answers

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);
  });
});
like image 188
JME Avatar answered Oct 01 '22 20:10

JME