DEV Community

loading...
Cover image for To Be Or Not To Be

To Be Or Not To Be

rfornal profile image bob.js ・2 min read

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 };
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

But b and c represent functionally equivalent objects; they both look like ...

{ foo: { bar: 'baz' } }
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Reference

Conclusion

While there are similarities between toBe and toEqual, they are clearly do not provide the same functionality.

Discussion (0)

pic
Editor guide