Skip to content Skip to sidebar Skip to footer

Testing Objects Equality In Nodejs

We are writing tests for a program. We want to write a functionnal test that verifies that the output of the program matches some expectation. The object returned is a complex JS o

Solution 1:

Node has the built in assert module meant for testing. This has a method called deepEqual for deep equality checking.

Function signature is:

assert.deepEqual(actual, expected, [message])

Quickly written function for testing deepEquality and returning diff:

// Will test own properties onlyfunctiondeepEqualWithDiff(a, e, names){
  var dif = {};
  var aKeys = Object.keys(a);
  var eKeys = Object.keys(e);

  var cKeys = aKeys;
  var dKeys = eKeys;
  var c = a;
  var d = e;
  var names = {
    c: names ? names['a'] : 'Actual',
    d: names ? names['e'] : 'Expected'
  }

  if(eKeys.length > aKeys.length){
    cKeys = eKeys;
    dKeys = aKeys;
    c = e;
    d = a;
    names = {
      d: names ? names['a'] : 'Actual',
      c: names ? names['e'] : 'Expected'
    }
  }


  for(var i = 0, co = cKeys.length; i < co; i++){
    var key = cKeys[i];
    if(typeof c[key] !== typeof d[key]){
      dif[key] = 'Type mismatch ' + names['c'] + ':' + typeof c[key] + '!==' + names['d'] + typeof d[key];
      continue;
    }
    if(typeof c[key] === 'function'){
      if(c[key].toString() !== d[key].toString()){
        dif[key] = 'Differing functions';
      }
      continue;
    }
    if(typeof c[key] === 'object'){
      if(c[key].length !== undefined){ // arrayvar temp = c[key].slice(0);
        temp = temp.filter(function(el){
          return (d[key].indexOf(el) === -1);
        });
        var message = '';
        if(temp.length > 0){
          message += names['c'] + ' excess ' + JSON.stringify(temp);
        }

        temp = d[key].slice(0);
        temp = temp.filter(function(el){
          return (c[key].indexOf(el) === -1);
        });
        if(temp.length > 0){
          message += ' and ' + names['d'] + ' excess ' + JSON.stringify(temp);
        }
        if(message !== ''){
          dif[key] = message;
        }
        continue;
      }
      var diff = deepEqualWithDiff(c[key], d[key], {a:names['c'],e:names['d']});
      if(diff !== true && Object.keys(diff).length > 0){
        dif[key] = diff;
      }
      continue;
    }
    // Simple types left soif(c[key] !== d[key]){
      dif[key] = names['c'] + ':' + c[key] + ' !== ' + names['d'] + ':' + d[key]; 
    }
  }
  returnObject.keys(dif).length > 0 ? dif : true;
}

Solution 2:

JavaScript doesn't support object deep equality out of the box and I am not aware of anything built into the NodeJS API either.

My bet would probably be Underscore and the isEqual function.

npm install underscore

var _ = require('underscore');
var moe   = {name : 'moe', luckyNumbers : [13, 27, 34]};
varclone = {name : 'moe', luckyNumbers : [13, 27, 34]};
moe == clone;
=> false
_.isEqual(moe, clone);
=> true

Although most Node testing frameworks should also contain an object deep equality assertion but you didn't mention which one you are using.

Solution 3:

deep-diff does what OP is asking for. It can compare two javascript objects / JSON objects and list the differences in a way that your code can access.

This is an old question so this library probably didn't exist at the time the question was asked.

Solution 4:

Note that Node's deepEqual() is deprecated since Node.js v9.9.0, use deepStrictEqual() instead:

const assert = require('assert');

constactual = {
  a: {
    name: 'some',
    b: {
      name: 'thing',
    },
  },
};

const expected = {
  a: {
    name: 'thing',
    b: {
      name: 'some',
    },
  },
};

assert.deepStrictEqual(actual, expected, 'Expect names to be equal.');

Pro Tip: If you don't use a custom message in deepStrictEqual, you will get a nice colorful output of the differences between the two objects:

enter image description here

Solution 5:

While I think the basics of object comparison have already been covered (see here and others), if you're looking for a quick and dirty way to execute these tests and see the diff between two non-equal objects, you can just run your tests using nodeunit within the Webstorm IDE (here)

Webstorm integrates particularly well with nodeunit, and for any test.equals() or test.deepEquals() assertions it provides a viewable diff with highlighting to show your descrepencies. I highly recommend the IDE for how well it integrates testing into my js development cycle.

Now, if you need the results of that test/diff to be accessible within your code, this obviously isn't enough for you and I'd recommend copying a couple of the deepEquals comparators from the first link I listed.

Good luck,

Brian

Post a Comment for "Testing Objects Equality In Nodejs"