Understanding Sinon.js's yield(), yields(), and callsArg()

TimeEmit picture TimeEmit · Apr 14, 2013 · Viewed 28.3k times · Source

What is the difference between

  • stub.yield([arg1, arg2, ...])
  • spy.yields([arg1, arg2, ...])
  • stub.callsArg(index)

in the Sinon.js stub library?

stub.yield() is the only one that I've been able to grasp:

  stub = sinon.stub(API, 'call_remote');
  callback = sinon.spy();
  API.call_remote('help', callback);
  @stub.yield( "solution!" );
  @stub.calledOnce.should.be.true;
  @callback.calledOnce.should.be.true;
  @callback.args[0][0].should.eql( "solution!" );

As tested with should.js, would have all assertions pass.

Are there similar test patterns for stub.yields() and stub.callsArg(index)?

The documentation does not provide any examples to clarify these other two methods but I am curious about them.

Answer

Travis Kaufman picture Travis Kaufman · Aug 15, 2013

I believe the methods, as outlined in the documentation, are as follows:

  • spy.yield
  • stub.yields
  • stub.callsArg

The main difference between yields and callsArg can be found in sinon's documentation for yields:

If a method accepts more than one callback, you need to use callsArg to have the stub invoke other callbacks than the first one.

yields will call the first function argument it encounters with any optional arguments you provide to it. callsArg will attempt to invoke the function argument at the given index within that call's arguments object, and does not pass any arguments to it (you can use callArgWith for that behavior).

spy.yield is very similar to stub.yields except it is part of the spy API and it calls all callbacks passed to it.

Here's some examples demonstrating the differences (forgive me if the examples are a bit contrived):

Yields:

var fn = sinon.expectation.create().withArgs(1, 2);
var stub = sinon.stub().yields(1, 2);
stub(fn);
fn.verify();

CallsArg:

var f1 = sinon.expectation.create().never();
var f2 = sinon.expectation.create().once();
var stub = sinon.stub().callsArg(1);
stub(f1, f2);
f1.verify();
f2.verify();

Yield:

var f1 = sinon.expectation.create().once();
var f2 = sinon.expectation.create().once();
var stub = sinon.stub().yield();
stub(f1, f2);
f1.verify();
f2.verify();