Skip to content

Jest Truthiness Matchers

JavaScript treats values like 0, '', null, undefined, and NaN as falsy, and everything else as truthy. This lesson covers the Jest matchers built specifically around that concept.

toBeTruthy() and toBeFalsy()

.toBeTruthy() passes if the value would evaluate as true in a boolean context (an if statement), and .toBeFalsy() passes for the opposite. These are intentionally loose — they don't check for a specific value, only its "truthy-ness".

Use these when you care about a general true/false-like outcome ("is a user logged in?") rather than a specific value ("is the count exactly 3?"), where a more precise matcher like .toBe() is a better fit.

expect('hello').toBeTruthy();
expect(1).toBeTruthy();
expect(0).toBeFalsy();
expect('').toBeFalsy();
expect(null).toBeFalsy();

Any of JavaScript's falsy values (0, '', null, undefined, NaN, false) pass .toBeFalsy().

Precise Null and Undefined Checks

expect(value).toBeNull();
expect(value).toBeUndefined();
expect(value).toBeDefined();
  • .toBeNull() passes only for the exact value null, not other falsy values.
  • .toBeUndefined() passes only for the exact value undefined.
  • .toBeDefined() is the exact opposite of .toBeUndefined().
  • Use these when the specific null/undefined distinction actually matters to your logic.

Truthiness Matchers Cheat Sheet

How to check truthy, falsy, null, and undefined values precisely.

Matcher Passes For
.toBeTruthy() Any truthy value
.toBeFalsy() Any falsy value (0, '', null, undefined, NaN, false)
.toBeNull() Exactly null
.toBeUndefined() Exactly undefined
.toBeDefined() Anything except undefined
.not.toBeNull() Anything except null

Why Precision Matters Between Falsy Values

.toBeFalsy() cannot tell you *which* falsy value you got — 0, '', and null all pass equally. If your function's contract specifically promises to return null (not 0 or an empty string) when nothing is found, .toBeNull() catches regressions that .toBeFalsy() would silently let through.

function findUser(id) {
  // bug: returns 0 instead of null when not found
  return users.find((u) => u.id === id) ?? 0;
}

expect(findUser(999)).toBeFalsy();  // misleadingly passes
expect(findUser(999)).toBeNull();   // correctly FAILS, exposing the bug

Testing Boolean Flags Directly

For functions that return an actual boolean, prefer .toBe(true)/.toBe(false) over .toBeTruthy()/.toBeFalsy() when you specifically expect a boolean type, not just a truthy/falsy value. This catches bugs where a function accidentally returns something like 1 or '' instead of a real boolean.

expect(isEmailValid('a@b.com')).toBe(true);
expect(isEmailValid('not-an-email')).toBe(false);

Common Mistakes

  • Using .toBeTruthy()/.toBeFalsy() when a specific value check like .toBeNull() or .toBe(false) would catch more bugs.
  • Assuming .toBeFalsy() means the value is false; it also passes for 0, '', null, undefined, and NaN.
  • Testing a function that should return a strict boolean with .toBeTruthy() instead of .toBe(true).
  • Forgetting that NaN is falsy, causing .toBeFalsy() to mask a NaN-producing bug.

Key Takeaways

  • .toBeTruthy()/.toBeFalsy() check general truthy/falsy behavior, not a specific value.
  • .toBeNull() and .toBeUndefined() check for those exact values precisely.
  • Prefer precise matchers whenever your function's contract specifies an exact return value.
  • Boolean-returning functions are better tested with .toBe(true)/.toBe(false).

Pro Tip

If you catch yourself reaching for .toBeTruthy(), pause and ask what exact value you actually expect. There is almost always a more precise matcher available.