Understanding Jest Matchers: A Comprehensive Guide with Examples

Jest is a popular JavaScript testing framework that simplifies the process of writing and executing tests for your code. One of the key features that make Jest powerful is its extensive set of matchers. Matchers are functions provided by Jest that allow you to assert specific conditions in your tests. In this article, we’ll explore Jest matchers in-depth, providing clear explanations and practical examples to help you master their usage.

What are Jest Matchers?

Matchers in Jest are functions that check if a certain condition is met during the test execution. They enable you to write expressive and readable assertions, making it easier to understand the intent of your tests. Jest comes with a variety of built-in matchers that cover common use cases in testing.

Basic Matchers

Let’s start with some basic matchers that Jest provides:

1. toBe()

The toBe matcher is used for exact equality checks. It compares values using === and is suitable for primitive data types.

test('adds 1 + 2 to equal 3', () => {
  expect(1 + 2).toBe(3);
});

2. toEqual()

The toEqual matcher is used for deep equality checks. It recursively checks every field of an object or array.

test('checks if two objects are equal', () => {
  const obj1 = { a: 1, b: 2 };
  const obj2 = { b: 2, a: 1 };

  expect(obj1).toEqual(obj2);
});

Truthiness Matchers

Jest provides matchers for checking truthiness and falsiness:

1. toBeTruthy() and toBeFalsy()

Use toBeTruthy to assert that a value is truthy and toBeFalsy for falsy values.

test('checks if a value is truthy', () => {
  const result = someFunction();

  expect(result).toBeTruthy();
});

Numeric Matchers

When dealing with numbers, Jest offers matchers to handle various scenarios:

1. toBeGreaterThan(), toBeGreaterThanOrEqual(), toBeLessThan(), toBeLessThanOrEqual()

These matchers allow you to compare numeric values.

test('checks if a value is greater than another', () => {
  const price = calculateTotalPrice();

  expect(price).toBeGreaterThan(0);
});

String Matchers

Jest provides matchers for string comparisons:

1. toMatch()

Use toMatch to check if a string matches a regular expression or includes a substring.

test('checks if a string contains a specific substring', () => {
  const message = generateMessage();

  expect(message).toMatch(/hello/);
});

Array Matchers

Jest includes matchers for array-related assertions:

1. toContain()

Use toContain to check if an array contains a specific item.

test('checks if an array contains a specific item', () => {
  const colors = getAvailableColors();

  expect(colors).toContain('red');
});

Custom Matchers

Jest allows you to create custom matchers tailored to your specific needs. This can enhance the readability and maintainability of your tests.

expect.extend({
  toBeEven(received) {
    const pass = received % 2 === 0;
    if (pass) {
      return {
        message: () => `expected ${received} not to be even`,
        pass: true,
      };
    } else {
      return {
        message: () => `expected ${received} to be even`,
        pass: false,
      };
    }
  },
});

test('checks if a number is even', () => {
  const number = getRandomNumber();

  expect(number).toBeEven();
});

Object Matchers

toHaveProperty()

This matcher checks if an object has a specified property.

test('checks if an object has a specific property', () => {
  const user = {
    id: 1,
    username: 'john_doe',
    email: 'john@example.com',
  };

  expect(user).toHaveProperty('username');
});

toContainEqual()

Verifies that an array or iterable contains an expected item or subset.

test('checks if an array contains a specific subset', () => {
  const users = [
    { id: 1, username: 'john_doe' },
    { id: 2, username: 'jane_doe' },
  ];

  expect(users).toContainEqual({ id: 2, username: 'jane_doe' });
});

Function Matchers

toThrow()

Asserts that a function throws an error when called.

test('checks if a function throws an error', () => {
  const faultyFunction = () => {
    throw new Error('Something went wrong');
  };

  expect(faultyFunction).toThrow();
});

toBeCalled(), toHaveBeenCalled(), toHaveBeenCalledTimes()

Matchers for checking if a function or mock function has been called.

test('checks if a function has been called', () => {
  const mockFunction = jest.fn();

  someFunctionThatCallsMock(mockFunction);

  expect(mockFunction).toBeCalled();
  expect(mockFunction).toHaveBeenCalledTimes(1);
});

Promise Matchers

resolves, rejects

These matchers are used with asynchronous code to check if a Promise resolves or rejects.

test('checks if a Promise resolves with a specific value', async () => {
  const result = await asyncFunction();

  expect(result).resolves.toBe('expectedValue');
});

Snapshot Matchers

toMatchSnapshot(), toMatchInlineSnapshot()

Snapshot testing allows you to capture the output of a component or data structure and compare it to a stored snapshot.

test('captures a component snapshot', () => {
  const component = render(<MyComponent />);
  expect(component).toMatchSnapshot();
});

Conclusion

Jest matchers are powerful tools that make writing tests more straightforward and enjoyable and cater to various testing scenarios. By combining and customizing these matchers, you can create robust tests that cover different aspects of your code. Regularly exploring the Jest documentation and staying updated with new releases can introduce you to additional matchers and features that enhance your testing experience. Happy testing!