11

If I have a stub for a function that takes 2 callbacks, how can I wire up sinon.js to call both callbacks when the stubbed function is invoked?

For example - here's function that I want to stub which takes 2 functions as arguments:

function stubThisThing(one, two) {
   ... one and two are functions ...
   ... contents stubbed by sinon.js ...
}

I can use sinon to call either one of the arguments:

stubbedThing.callsArg(0);

or

stubbedThing.callsArg(1);

but I can't seem to get both to be called. If I try:

stubbedThing.callsArg(0).callsArg(1);

or

stubbedThing.callsArg(0);
stubbedThing.callsArg(1);

then sinon will only ever call the second argument. If I wire it up in the other order, then sinon will call the first arg. However, I'd like both to be called one after the other.

serg10
  • 31,923
  • 16
  • 73
  • 94
  • have you checked `calledWith` method – Pawan Apr 27 '15 at 05:40
  • @Pawan - Do you mean the `calledWith` function from the spy API? That's really not what I am looking for. I want to alter the behaviour of a stub. – serg10 Apr 27 '15 at 07:50
  • sinon.js only supports calling **at most one callback per stub per call**. It can call multiple callbacks on multiple calls eg. `stubbedThing.onCall(0).callsArg(0); stubbedThing.onCall(1).callsArg(1);`. Or you can manually `callArg` after your `stubbedThing` is called: e.g. `stubbedThing(firstArg, secondArg); stubbedThing.callArg(0); //calls firstArgs; stubbedThing.callArg(1) // calls secondArg` – nemesv Apr 27 '15 at 15:41
  • @serg10: why dont you put this question on their github as an issue, may be they will come up with something.. – Pawan Apr 28 '15 at 04:37

2 Answers2

7

This is not a classic scenario, since not many methods would call two methods sequentially, and I guess thats why it isn't supported. But, be calm, the solution is easy:

var subject = { 
    method: function(one, two) {} 
};

var stub = sinon.stub(subject, 'method', function(one, two) { 
    one(); 
    two(); 
});

subject.method(
    function() { console.log('callback 1'); }, 
    function() { console.log('callback 2'); });

Side note: This also gives the option for choosing if one or two should be called first.

Emil Ingerslev
  • 4,645
  • 2
  • 24
  • 18
1

Why don't you skip sinon altogether?

var obj = { stubMe: function(cb1, cb2) {} };
var originalMethod = obj.stubMe;

obj.stubMe = function(cv1, cb2) { 
  //Whatever logic you wish
  cb1(); 
  cb2(); 
}; 

//Do your test

obj.stubMe = originalMethod; //Restore

This way you can even continue to use sinon's APIs, if you wish:

var stub = sinon.stub();
obj.stubMe = function(cb1, cb2) { 
  stub.apply(stub, arguments);
  //Rest of whatever logic you wanted here
};

obj.stubMe();
expect(stub.calledOnce()).to.be(true); //That would pass

What'd you think?

Arseny Smoogly
  • 600
  • 2
  • 7