Mocha/Chai testing expected vs actual arrays of objects

Pauli Price picture Pauli Price · Jan 1, 2014 · Viewed 9.7k times · Source

What's the best way to assert that the expected results matches the actual results when both are arrays of objects? My immediate thought was to use Array prototype filter and check that the intersection is the same size as expected, i.e.:

describe('select',function(){
  it("should return selected columns", function(done) {
    var query = "select lunchTime, name";

    var actual = ... results of the query, an array of anonymous objects ...

    // expected results
    var expected = [{"lunchTime": "12:00:00", "name": "John"}, 
                   {"lunchTime": "12:00:00", "name": "Dave"}, 
                   {"lunchTime": "13:00:00", "name": "Sally"}, 
                   {"lunchTime": "12:00:00", "name": "Ben"}, 
                   {"lunchTime": "12:00:00", "name": "Dana"}, 
                   {"lunchTime": "13:00:00", "name": "Mike"}];

    var intersection = actual.filter(function(n) {
        return expected.indexOf(n) != -1
    });

    expect(intersection).to.have.length(expected.length);
    expect(actual).to.have.length(expected.length);
  });
});

Does this approach make sense? Is there a better way to assert the query results match expectations?

Answer

Jason Walton picture Jason Walton · May 15, 2015

As you noted, for sets, you can use:

expect(actual).to.have.members(expected);

This will fail if there are any members in expected that are not in actual, and vice versa.

You can also do:

expect(actual).to.contain.members(expected);

Which will fail if there are members in expected that are not in actual, but will not fail if there are members in actual that are not in expected. (In other words, actual must be a superset of expected).

If you're comparing objects, you probably want to deep compare:

expect(actual).to.deep.have.same.members(expected);

e.g.:

expect([{a:'a'}, {a:'b'}]).to.deep.have.same.members([{a:'a'}, {a:'b'}]);

(edited: to.have.same.members() is actually the same as to.have.members().)