Matchers and Assertions
Jest provides a rich set of matchers to verify different types of values. Understanding these matchers is essential for writing expressive, readable tests.
Common Matchers
Exact Equality: toBe
Use toBe for primitive values (numbers, strings, booleans):
test('exact equality', () => {
expect(2 + 2).toBe(4);
expect('hello').toBe('hello');
expect(true).toBe(true);
});
Important: toBe uses Object.is for comparison. For objects, it checks reference equality:
const obj = { a: 1 };
expect(obj).toBe(obj); // Pass - same reference
expect({ a: 1 }).toBe({ a: 1 }); // Fail! Different objects
Object Equality: toEqual
Use toEqual to compare object contents:
test('object equality', () => {
const data = { name: 'Alice', age: 30 };
expect(data).toEqual({ name: 'Alice', age: 30 }); // Pass!
});
test('array equality', () => {
expect([1, 2, 3]).toEqual([1, 2, 3]); // Pass!
});
test('nested objects', () => {
const user = {
name: 'Alice',
address: { city: 'NYC', zip: '10001' }
};
expect(user).toEqual({
name: 'Alice',
address: { city: 'NYC', zip: '10001' }
});
});
Strict Object Equality: toStrictEqual
toStrictEqual is stricter than toEqual:
test('toEqual vs toStrictEqual', () => {
// toEqual ignores undefined properties
expect({ a: 1, b: undefined }).toEqual({ a: 1 }); // Pass
// toStrictEqual does not
expect({ a: 1, b: undefined }).toStrictEqual({ a: 1 }); // Fail!
});
Truthiness Matchers
Test for null, undefined, and boolean values:
test('null and undefined', () => {
const n = null;
const u = undefined;
const zero = 0;
expect(n).toBeNull(); // Only matches null
expect(u).toBeUndefined(); // Only matches undefined
expect(n).toBeDefined(); // Matches anything not undefined
// Truthiness
expect(zero).toBeFalsy(); // 0, '', null, undefined, false
expect(1).toBeTruthy(); // Anything not falsy
});
Number Matchers
For numeric comparisons:
test('number comparisons', () => {
const value = 10;
expect(value).toBeGreaterThan(5);
expect(value).toBeGreaterThanOrEqual(10);
expect(value).toBeLessThan(20);
expect(value).toBeLessThanOrEqual(10);
// For floating point, use toBeCloseTo
expect(0.1 + 0.2).toBeCloseTo(0.3); // Handles float precision
expect(0.1 + 0.2).not.toBe(0.3); // This would fail!
});
String Matchers
For string testing:
test('string matchers', () => {
const message = 'Hello, World!';
expect(message).toMatch(/Hello/); // Regex match
expect(message).toMatch('World'); // Substring match
expect(message).toContain('World'); // Contains substring
expect(message).toHaveLength(13); // String length
});
Array Matchers
For arrays and iterables:
test('array matchers', () => {
const fruits = ['apple', 'banana', 'cherry'];
expect(fruits).toContain('banana');
expect(fruits).toHaveLength(3);
expect(fruits).toEqual(expect.arrayContaining(['banana', 'apple']));
// Check for specific item in array of objects
const users = [
{ name: 'Alice', age: 30 },
{ name: 'Bob', age: 25 }
];
expect(users).toContainEqual({ name: 'Alice', age: 30 });
});
Object Matchers
For object properties:
test('object matchers', () => {
const user = {
name: 'Alice',
email: 'alice@example.com',
age: 30
};
// Check for specific property
expect(user).toHaveProperty('name');
expect(user).toHaveProperty('name', 'Alice');
expect(user).toHaveProperty('email', expect.stringContaining('@'));
// Check object contains subset
expect(user).toMatchObject({
name: 'Alice',
age: 30
});
// Nested properties
const company = {
name: 'TechCorp',
address: { city: 'NYC', zip: '10001' }
};
expect(company).toHaveProperty('address.city', 'NYC');
});
Exception Matchers
For testing errors:
function throwError() {
throw new Error('Something went wrong');
}
function throwCustomError() {
throw new TypeError('Invalid type');
}
test('exception matchers', () => {
// Must wrap in a function
expect(() => throwError()).toThrow();
expect(() => throwError()).toThrow('Something went wrong');
expect(() => throwError()).toThrow(/wrong/);
expect(() => throwError()).toThrow(Error);
expect(() => throwCustomError()).toThrow(TypeError);
});
Note: Always wrap the throwing code in a function () =>. Otherwise the error throws before expect can catch it!
Asymmetric Matchers
For flexible matching:
test('asymmetric matchers', () => {
const user = {
id: 123,
name: 'Alice',
createdAt: new Date()
};
expect(user).toEqual({
id: expect.any(Number), // Any number
name: expect.any(String), // Any string
createdAt: expect.any(Date) // Any Date instance
});
expect(['a', 'b', 'c']).toEqual(
expect.arrayContaining(['a', 'c']) // Contains at least these
);
expect({ a: 1, b: 2, c: 3 }).toEqual(
expect.objectContaining({ a: 1 }) // Contains at least this
);
expect('hello world').toEqual(
expect.stringContaining('world') // Contains substring
);
expect('hello world').toEqual(
expect.stringMatching(/^hello/) // Matches regex
);
});
Try It: Choose the Right Matcher
Custom Matchers
You can create custom matchers for domain-specific assertions:
// In jest.setup.js or test file
expect.extend({
toBeValidEmail(received) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const pass = emailRegex.test(received);
return {
message: () =>
pass
? `expected ${received} not to be a valid email`
: `expected ${received} to be a valid email`,
pass,
};
},
});
// In tests
test('validates email', () => {
expect('user@example.com').toBeValidEmail();
expect('invalid-email').not.toBeValidEmail();
});
Matcher Cheat Sheet
| Matcher | Use For |
|---|---|
toBe(value) | Primitive equality |
toEqual(value) | Object/array deep equality |
toStrictEqual(value) | Strict object equality |
toBeNull() | Checking null |
toBeUndefined() | Checking undefined |
toBeDefined() | Checking not undefined |
toBeTruthy() | Checking truthy values |
toBeFalsy() | Checking falsy values |
toBeGreaterThan(n) | Number > n |
toBeLessThan(n) | Number < n |
toBeCloseTo(n) | Float comparison |
toMatch(regex|str) | String matching |
toContain(item) | Array/string contains |
toHaveLength(n) | Array/string length |
toHaveProperty(key) | Object has property |
toThrow(error?) | Function throws |
Key Takeaways
- Use
toBefor primitives,toEqualfor objects - Use
toBeCloseTofor floating-point comparisons - Use
toThrowwith a function wrapper for error testing - Asymmetric matchers (
expect.any(),expect.objectContaining()) provide flexibility - Create custom matchers for domain-specific assertions
- Choose the most specific matcher for clearer test failures
Next, we'll learn how to test functions effectively with different input types and edge cases!

