Asserting a specific call to the stub was done with the required arguments using sinon

Let's say you are testing a function that will call a dependency multiple times with different arguments:

var sut = {
    ImportantFunction: function(dependency){
        dependency("a", 1);
        dependency("b", 2);
    }
};

      

Using QUnit + Sinon, and assuming the order of the calls is not important , I could write the following test that ensures the function invokes the dependency as expected:

test("dependency was called as expected", function () {
    var dependencyStub = sinon.stub();

    sut.ImportantFunction(dependencyStub);

    ok(dependencyStub.calledTwice, "dependency was called twice");            
    sinon.assert.calledWith(dependencyStub, "a", 1);
    sinon.assert.calledWith(dependencyStub, "b", 2);
});

      

But what if order is important and I want the test to take it into account? What's the best way to write a test like this with QUnit + Sinon?

I have used the following approach, but I am missing the descriptive failure message provided by sinon assertion (which shows the expected and actual values). To do this, I just added a few descriptive messages manually, but this is not nearly as useful as having an error message with expected and actual values ​​(and needs to be maintained manually).

ok(dependencyStub.firstCall.calledWith("a", 1), "dependency called with expected args 'a', 1");
ok(dependencyStub.secondCall.calledWith("b", 2), "dependency called with expected args 'b', 2");

      

Is there a way to use a type assertion sinon.assert.calledWith

for a specific call such as the first or second call?

Setting up a sample in this violin

+3


source to share


2 answers


You can use sinon.assert.callOrder(spy1, spy2, ...)

either spy1.calledBefore(spy2)

or spy2.calledAfter(spy1)

.



They can also be used with a result spy.calledWith(...)

, for example. sinon.assert.callOrder(spy.withArgs('a'), spy.withArgs('b'))

...

+5


source


And just as I was creating the sample script I found a solution ...

In my code, I was using version 1.7.1 from Sinon, but when writing a fiddle using the latest version of Sinon (1.14.1 as of today), I just realized that you can pass a specific spyCall method assert.calledWith

. This means that you can write the following:

sinon.assert.calledWith(dependencyStub.firstCall, "a", 1);
sinon.assert.calledWith(dependencyStub.secondCall, "b", 2);

      

So, the test I wanted to create can be nicely written:

test("dependency was called multiple times as expected - with order", function () {
    var dependencyStub = sinon.stub();

    sut.ImportantFunction(dependencyStub);

    sinon.assert.calledTwice(dependencyStub);
    sinon.assert.calledWith(dependencyStub.firstCall, "a", 1);
    sinon.assert.calledWith(dependencyStub.secondCall, "b", 2);    
});

      



Fiddle here

Edit

Found in the github repository the discussion that introduced this change. By the time you change the merge with master, this should work with version 1.13.0 and newer.

If you are using older versions you can use mantoni's solution:

test("dependency was called multiple times as expected with order - pre 1.13.0", function () {
    var dependencyStub = sinon.stub();

    sut.ImportantFunction(dependencyStub);

    sinon.assert.calledTwice(dependencyStub);
    sinon.assert.callOrder(
        dependencyStub.withArgs("a", 1), 
        dependencyStub.withArgs("b", 2));
});

      

+6


source







All Articles