I'm using Mocha to test a small module in my Express.js application. In this module, one of my functions returns an array. I want to test whether or not the array is correct for a given input. I am doing so like this:
suite('getWords', function(){
test("getWords should return list of numbers", function() {
var result = ['555', '867', '5309'];
assert.equal(result, getWords('555-867-5309'));
});
});
When this runs, I get the following assertion error:
AssertionError: ["555","867","5309"] == ["555","867","5309"]
However, when I change my test to an assert.deepEqual
, the test passes fine. I was wondering if it was a case of ==
vs ===
, but if I enter
[1,2,3] === [1,2,3]
into the node.js command line, I still get false.
Why do arrays not compare the way other values do (e.g. 1 == 1
)? and what is the difference between assert.equal and assert.deepEqual?
Why do arrays not compare the way other values do (e.g. 1==1)
Numbers, strings, booleans, null
, and undefined
are values, and are compared as you might expect. 1 == 1
, 'a' == 'a'
, and so on. The difference between ===
and ==
in the case of values is that ==
will attempt to perform type conversion first, which is why '1' == 1
but not '1' === 1
.
Arrays, on the other hand, are objects. ===
and ==
in this case do not signify that the operands are semantically equal, but that they refer to the same object.
what is the difference between assert.equal and assert.deepEqual?
assert.equal
behaves as explained above. It actually fails if the arguments are !=
, as you can see in the source. Thus it fails for your arrays of numbers strings because although they are essentially equivalent, they are not the same object.
Deep (aka structural) equality, on the other hand, does not test whether the operands are the same object, but rather that they're equivalent. In a sense, you could say it forces objects to be compared as though they're values.
var a = [1,2,3]
var b = a // As a and b both refer to the same object
a == b // this is true
a === b // and this is also true
a = [1,2,3] // here a and b have equivalent contents, but do not
b = [1,2,3] // refer to the same Array object.
a == b // Thus this is false.
assert.deepEqual(a, b) // However this passes, as while a and b are not the
// same object, they are still arrays containing 1, 2, 3
assert.deepEqual(1, 1) // Also passes when given equal values
var X = function() {}
a = new X
b = new X
a == b // false, not the same object
assert.deepEqual(a, b) // pass, both are unadorned X objects
b.foo = 'bar'
assert.deepEqual(a, b) // fail!