How to match an array of objects with sinon.js?

Sinon has matchers on the content of arrays, for example, sinon.match.array.deepEquals

This works:

var mystub = sinon.stub();

var myarg = { val: 1, mylist: [ {a:1}, {b:2}, {c:3,d:4} ] };

mystub(myarg);

sinon.assert.calledWith(mystub,
  sinon.match({
    val: 1,
    mylist: sinon.match.array.deepEquals([ {a:1}, {b:2}, {c:3,d:4} ])
  })
);

The custom matching function in the accepted answer is useful to know about but total overkill for this simple use case. To build on the useful answer from Eryk Warren, how about this:

// match each element of the actual array against the corresponding entry in the expected array
sinon.assert.match(actual, expected.map(sinon.match));

Custom matcher.

I recommend writing your own custom sinon matcher.

You can write it in a way that it is general and easy to read when it gets used.

Here is an example approach:

// usage
...withArgs(sinon.match(deepMatch({
    val: 1,
    mylist: [{a:1}, {b:2}, {c:3,d:4}]
})));


// custom matcher
const deepMatch = (expectation) => (actual) => {
    return Object.keys(expectation).every(key => {
        if (checkIfItsObject(expectation[key])) {
            // value is also an object, go deeper and then compare etc.
        } else {
            // compare and return boolean value accordingly
        }
    });
};

// note: checkIfItsObject is pseudocode - there are many ways to
// check if an object is an object so I did not want to complicate
// this code example here

This is an old posting, but I couldn't find the right answer for this question.

Sinon supports nested matchers. So to test the matching of deep object, you can do the following:

const mystub = sinon.stub();
const myarg = {
  val: 1,
  mylist: [{ a: 1, x: 'foo' }, { b: 2, y: 'bar' }, { c: 3, d: 4, e: 5 } ],
};

mystub(myarg);

sinon.assert.calledOnce(mystub);
sinon.assert.calledWithMatch(mystub, {
  val: 1,
  mylist: [
    sinon.match({ a: 1 }),
    sinon.match({ b: 2 }),
    sinon.match({ c: 3, d: 4 }),
  ],
});