In a discussion with a client about testing, the question came up about using toBe
or toEqual
. The assumption was that they were the same, one aliasing the other. This is absolutely not true.
Primitive Types
For primitive types such as numbers, booleans, or strings, there is no difference between toBe
and toEqual
; either one will work for values such as ... 5
, true
, or "this is a string"
.
Non-Primitive Types
To understand the difference between toBe
and toEqual
, start with some objects.
var a = { item: 'item-a' };
var b = { sub: a };
var c = { sub: a };
Using a strict comparison (===), some things in this scenario "the same":
b.sub.item === c.sub.item; // true
b.sub.item === a.item; // true
c.sub === b.sub; // true
But some things, even though they are "equal", are not "the same", since they represent objects that live in different locations in memory.
b === c; // false
Jasmine's toBe
matcher is nothing more than a wrapper for a strict equality comparison.
// These are the same
expect(c.sub).toBe(b.sub);
expect(c.sub === b.sub).toBe(true);
But b
and c
represent functionally equivalent objects; they both look like ...
{ foo: { bar: 'baz' } }
It would be great to be able to say that b
and c
are "equal" even if they do not represent the same object?
Enter toEqual
, which checks "deep equality" (does a recursive search through the objects to determine whether the values for their keys are equivalent). Both of the following tests will pass:
expect(b).not.toBe(c);
expect(b).toEqual(c);
More Detail
toEqual
has special handling for built in objects like String
, Number
, Boolean
, Date
, Error
, Element
and RegExp
. For other objects it recursively compares properties.
This is very different from the behavior of the equality operator, ==. For example:
var simpleObject = { item: 'simple' };
expect(simpleObject).toEqual({ item: 'simple' }); // true
simpleObject == { item: 'simple' }; // false
var castableObject = { toString: function(){ return 'cast' } };
expect(castableObject).toEqual('cast'); // false
castableObject == 'cast'; // true
Reference
Conclusion
While there are similarities between toBe
and toEqual
, they are clearly do not provide the same functionality.
Top comments (0)