Sinon: Mocks don't work well with onCall

Created on 12 Jun 2014  ·  4Comments  ·  Source: sinonjs/sinon

I can't get mocks to work with onCall and expected arguments.
The code below gives Object #<Object> has no method 'withExactArgs'

var mock = sinon.mock();

mock.exactly(2);
mock.onCall(0).withExactArgs("arg1", "arg2").returns("foo");

mock.verify();

The withExactArgs method is available on the stub property: mock.onCall(0).stub.withExactArguments.

Is this intended behaviour or a bug?

Most helpful comment

It is neither intended behaviour nor a bug. You're mixing metaphors. onCall and withArgs are both ways of identifying a method invocation.

// So either, 

mock.onCall(0).returns("foo")

// OR

mock.withArgs("arg1", "arg2").returns("foo")

// but not both

Your second example is flawed for the same reason and should probably be re-written using a stub.

    var stub = sinon.stub();

    stub.withArgs("bar1", "bar2").returns("bar");
    stub.withArgs("foo1", "foo2").returns("foo");

    stub("bar1", "bar2");
    stub("foo1", "foo2");

    sinon.assert.calledTwice(stub);

    // verify the 2 calls
    sinon.assert.calledWithExactly(stub, "bar1", "bar2");
    sinon.assert.calledWithExactly(stub, "foo1", "foo2");

    // verify the 2 calls in order
    sinon.assert.callOrder(
        stub.withArgs("bar1", "bar2"),
        stub.withArgs("foo1", "foo2")
    );

Unfortunately, there's no withExactArgs on Stub.

All 4 comments

It seems like it doesn't work with .stub either. I get an error saying the method was called with the wrong arguments. Showing the arguments from the first call but the requirements from the second. As if it discards the onCall(0).

var mock = sinon.mock();

mock.exactly(2);
mock.onFirstCall().stub.withExactArgs("bar1", "bar2").returns("bar");
mock.onSecondCall().stub.withExactArgs("foo1", "foo2").returns("foo");

mock("bar1", "bar2");
mock("foo1", "foo2");

mock.verify();

Gives ExpectationError: Anonymous mock received wrong arguments ["bar1", "bar2"], expected ["foo1", "foo2"]

It is neither intended behaviour nor a bug. You're mixing metaphors. onCall and withArgs are both ways of identifying a method invocation.

// So either, 

mock.onCall(0).returns("foo")

// OR

mock.withArgs("arg1", "arg2").returns("foo")

// but not both

Your second example is flawed for the same reason and should probably be re-written using a stub.

    var stub = sinon.stub();

    stub.withArgs("bar1", "bar2").returns("bar");
    stub.withArgs("foo1", "foo2").returns("foo");

    stub("bar1", "bar2");
    stub("foo1", "foo2");

    sinon.assert.calledTwice(stub);

    // verify the 2 calls
    sinon.assert.calledWithExactly(stub, "bar1", "bar2");
    sinon.assert.calledWithExactly(stub, "foo1", "foo2");

    // verify the 2 calls in order
    sinon.assert.callOrder(
        stub.withArgs("bar1", "bar2"),
        stub.withArgs("foo1", "foo2")
    );

Unfortunately, there's no withExactArgs on Stub.

However...

You can identify individual calls to a stub, even when called multiple times with the same arguments. For example

stub.withArgs("foo")
  .onCall(0).returns("a")
  .onCall(1).returns("b");

stub.withArgs("bar")
  .onCall(0).returns("c")
  .onCall(1).returns("d");

If that helps?

@mantoni I think this issue can be closed

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fearphage picture fearphage  ·  3Comments

akdor1154 picture akdor1154  ·  4Comments

fearphage picture fearphage  ·  4Comments

stevenmusumeche picture stevenmusumeche  ·  3Comments

brettz9 picture brettz9  ·  3Comments