Every Jest assertion starts with expect(). This lesson explains what expect() actually returns, how matcher methods attach to it, and how the .not modifier lets you assert the opposite of a matcher.
What expect() Returns
expect(value) wraps a value in a special Jest object that exposes matcher methods like .toBe(), .toEqual(), and .toContain(). The wrapped value is often called the "actual" or "received" value, and it is compared against an "expected" value you pass into the matcher.
If the matcher's condition is not met, Jest throws an assertion error, which is what causes the test to fail and produces the readable diff you see in the terminal.
const total = 2 + 2;
expect(total).toBe(4); // passes
expect(total).not.toBe(5); // passes: total is NOT 5
.not inverts any matcher, letting you assert that a condition does *not* hold.
receivedValue is whatever your code under test actually produced.
matcherName is one of Jest's many built-in matchers, like .toBe() or .toEqual().
expectedValue is what you expect the received value to equal, contain, or match.
.not before the matcher inverts the assertion.
expect() Cheat Sheet
The most common ways expect() gets used in everyday tests.
Usage
Example
Basic equality
expect(2 + 2).toBe(4)
Deep equality
expect(obj).toEqual({ id: 1 })
Negation
expect(value).not.toBeNull()
Truthiness
expect(flag).toBeTruthy()
Throwing
expect(() => fn()).toThrow()
Async rejection
await expect(promise).rejects.toThrow()
Number of calls
expect(mockFn).toHaveBeenCalledTimes(2)
Counting Assertions with expect.assertions()
In async tests, it's possible for a test to pass "by accident" if an expect() inside a .then() or catch() callback never actually runs (for example, if a promise resolves instead of rejecting). expect.assertions(n) tells Jest exactly how many assertions should run during the test, causing it to fail if that number doesn't match.
test('rejects with an error', () => {
expect.assertions(1);
return fetchUser(-1).catch((err) => {
expect(err.message).toMatch('Invalid id');
});
});
If the promise unexpectedly resolves instead of rejecting, expect.assertions(1) catches the bug.
Chaining .not with Any Matcher
.not can precede any matcher, which is often clearer than trying to invert the logic yourself. It reads naturally: "expect this array to not contain that value."
Forgetting to return (or await) a promise inside a test, letting it pass before the assertion even runs.
Writing expect(value === expected).toBe(true) instead of just expect(value).toBe(expected).
Not using expect.assertions() in async error-handling tests, hiding silent test-pass bugs.
Overusing .not when a more specific positive matcher already exists (e.g. .toBeNull() instead of .not.toBeDefined() in some cases).
Key Takeaways
expect(value) wraps a value so matcher methods can be chained onto it.
A failed matcher throws an error, which Jest reports as a failing test with a diff.
.not inverts any matcher for precise negative assertions.
expect.assertions(n) guards against async tests that pass without actually asserting anything.
Pro Tip
When testing rejected promises or thrown errors, always pair the test with expect.assertions(n) or return/await the promise. It is one of the most common sources of silently-passing Jest tests.
You now understand how expect() and matchers work together. Next, explore Jest's full matcher library in more depth.