Skip to content

Jest Matchers

Matchers are the methods you chain onto expect() to describe what you're checking, from simple equality to deep object comparison. This lesson gives a broad tour of Jest's matcher library before we go deeper into each category.

What Matchers Do

A matcher is a method on the object returned by expect(). Each matcher checks a specific condition — equality, containment, type, numeric comparison, and more — and Jest reports a detailed failure message if the condition isn't met.

Jest ships dozens of built-in matchers, organized loosely into categories: equality (.toBe(), .toEqual()), truthiness (.toBeTruthy(), .toBeNull()), numbers (.toBeGreaterThan()), strings (.toMatch()), arrays/objects (.toContain(), .toHaveProperty()), and exceptions (.toThrow()).

expect(3 + 3).toBe(6);
expect({ name: 'Ada' }).toEqual({ name: 'Ada' });
expect('Hello World').toMatch(/World/);
expect([1, 2, 3]).toContain(2);
expect(() => { throw new Error('bad input'); }).toThrow('bad input');

Five different matcher categories used in a single snippet: equality, deep equality, regex matching, containment, and exceptions.

General Matcher Syntax

expect(received)[.not].matcherName(expected);
  • Every matcher follows the same pattern: expect(received) then a matcher method.
  • Matchers can take zero, one, or more arguments depending on what they check.
  • The optional .not inverts any matcher in the chain.
  • Some matchers are async-aware, like .resolves and .rejects, used before the matcher.

Jest Matchers Cheat Sheet

The most frequently used matchers across all categories.

Category Matcher Checks
Equality .toBe(x) Strict equality (Object.is)
Equality .toEqual(x) Deep/recursive equality
Truthiness .toBeTruthy() Value is truthy
Truthiness .toBeNull() Value is exactly null
Numbers .toBeGreaterThan(x) Numeric comparison
Numbers .toBeCloseTo(x) Floating point comparison
Strings .toMatch(regexOrStr) String matches pattern
Arrays .toContain(x) Array/iterable includes item
Objects .toHaveProperty(path) Object has a given key path
Exceptions .toThrow(errorOrMsg) Function throws on call

toBe() vs. toEqual()

This is the single most important matcher distinction in Jest. .toBe() uses Object.is() (essentially ===) so it only passes for primitives with the same value, or objects that are literally the same reference. .toEqual() instead recursively compares the contents of objects and arrays, ignoring reference identity.

const a = { name: 'Ada' };
const b = { name: 'Ada' };

expect(a).toBe(a);      // passes: same reference
expect(a).toBe(b);      // FAILS: different objects
expect(a).toEqual(b);   // passes: same contents

Use .toBe() for primitives, .toEqual() for objects and arrays.

Matcher Modifiers: .not, .resolves, .rejects

Modifiers change how a matcher is applied without changing the matcher itself. .not inverts the result. .resolves and .rejects unwrap a promise before applying the matcher, which is essential for testing asynchronous code cleanly.

expect(value).not.toBeNull();

await expect(fetchUser(1)).resolves.toEqual({ id: 1, name: 'Ada' });
await expect(fetchUser(-1)).rejects.toThrow('Invalid id');

Common Mistakes

  • Using .toBe() to compare two different object or array instances with the same contents.
  • Forgetting await before expect(promise).resolves... or .rejects....
  • Choosing an overly generic matcher (.toBeTruthy()) when a more specific one exists (.toHaveLength(3)).
  • Not knowing a relevant matcher exists and manually re-implementing the check with plain if statements.

Key Takeaways

  • Matchers are chained onto expect() to describe the exact condition being checked.
  • .toBe() checks strict/reference equality; .toEqual() checks deep structural equality.
  • .not inverts any matcher; .resolves/.rejects unwrap promises before matching.
  • Jest's matcher library covers equality, truthiness, numbers, strings, arrays/objects, and exceptions.

Pro Tip

Keep the official Jest "Expect" API page bookmarked. There is almost always a purpose-built matcher for what you're trying to check, and using it produces far better failure messages than a generic boolean check.