DEV Community

Cover image for To Be Or Not To Be
bob.ts
bob.ts

Posted on

6 1

To Be Or Not To Be

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.

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Top comments (1)

Collapse
 
thejaredwilcurt profile image
The Jared Wilcurt

Using toBe is an anti-pattern. Always use toEqual. dev.to/thejaredwilcurt/why-you-sho...

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay