Matchers

Matchers play a fundamental role in testing by allowing developers to assert the expected outcomes of their code.

In this lesson we will look at a variety of different matchers that are available in Vitest. These matchers are used to compare values, check for specific conditions, and verify the behavior of your code.

Basic Matchers

Matchers are functions that allow you to assert whether a value meets certain conditions. In this chapter, we’ll cover some of the most commonly used basic matchers in Vitest.

We will look at the following basic matchers:

  • toBe for strict equality
  • toEqual for deep equality
  • toBeTruthy / toBeFalsy for truthy and falsy checks
  • toBeNull / toBeUndefined / toBeDefined for checking null, undefined, and defined values

1.1 toBe

The toBe matcher checks for strict equality using ===.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Basic Matchers', () => {
	  it('should compare primitive values using toBe', () => {
	    const result = 2 + 2;
	    expect(result).toBe(4); // Asserts that result is strictly equal to 4
	  });
	});

1.2 toEqual

The toEqual matcher is used for deep equality checks, useful for objects and arrays.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Basic Matchers', () => {
	  it('should compare objects using toEqual', () => {
	    const obj = { name: 'John', age: 30 };
	    const expectedObj = { name: 'John', age: 30 };
	    expect(obj).toEqual(expectedObj); // Asserts that obj is deeply equal to expectedObj
	  });
	});

1.3 toBeTruthy / toBeFalsy

These matchers are used to check if a value is truthy or falsy.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Basic Matchers', () => {
	  it('should check truthy values using toBeTruthy', () => {
	    const value = 'Hello';
	    expect(value).toBeTruthy(); // Asserts that value is truthy
	  });
	
	  it('should check falsy values using toBeFalsy', () => {
	    const value = 0;
	    expect(value).toBeFalsy(); // Asserts that value is falsy
	  });
	});

1.4 toBeNull / toBeUndefined / toBeDefined

These matchers check for null, undefined, and defined values.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Basic Matchers', () => {
	  it('should check for null values using toBeNull', () => {
	    const value = null;
	    expect(value).toBeNull(); // Asserts that value is null
	  });
	
	  it('should check for undefined values using toBeUndefined', () => {
	    let value;
	    expect(value).toBeUndefined(); // Asserts that value is undefined
	  });
	
	  it('should check for defined values using toBeDefined', () => {
	    const value = 'defined';
	    expect(value).toBeDefined(); // Asserts that value is defined
	  });
	});

Numeric Matchers

Numeric matchers are used to compare numerical values in various ways. We’ll cover the most commonly used numeric matchers:

  • toBeGreaterThan for checking if a value is greater than another value
  • toBeGreaterThanOrEqual for checking if a value is greater than or equal to another value
  • toBeLessThan for checking if a value is less than another value
  • toBeLessThanOrEqual for checking if a value is less than or equal to another value
  • toBeCloseTo for comparing floating-point numbers

2.1 toBeGreaterThan

The toBeGreaterThan matcher is used to check if a value is greater than the expected value.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Numeric Matchers', () => {
	  it('should check if a value is greater than another value using toBeGreaterThan', () => {
	    const result = 10;
	    expect(result).toBeGreaterThan(5); // Asserts that result is greater than 5
	  });
	});

2.2 toBeGreaterThanOrEqual

The toBeGreaterThanOrEqual matcher is used to check if a value is greater than or equal to the expected value.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Numeric Matchers', () => {
	  it('should check if a value is greater than or equal to another value using toBeGreaterThanOrEqual', () => {
	    const result = 10;
	    expect(result).toBeGreaterThanOrEqual(10); // Asserts that result is greater than or equal to 10
	  });
	});

2.3 toBeLessThan

The toBeLessThan matcher is used to check if a value is less than the expected value.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Numeric Matchers', () => {
	  it('should check if a value is less than another value using toBeLessThan', () => {
	    const result = 3;
	    expect(result).toBeLessThan(5); // Asserts that result is less than 5
	  });
	});

2.4 toBeLessThanOrEqual

The toBeLessThanOrEqual matcher is used to check if a value is less than or equal to the expected value.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Numeric Matchers', () => {
	  it('should check if a value is less than or equal to another value using toBeLessThanOrEqual', () => {
	    const result = 5;
	    expect(result).toBeLessThanOrEqual(5); // Asserts that result is less than or equal to 5
	  });
	});

2.5 toBeCloseTo

The toBeCloseTo matcher is used for comparing floating-point numbers. It allows you to specify the precision of the comparison.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Numeric Matchers', () => {
	  it('should check if a floating-point value is close to another value using toBeCloseTo', () => {
	    const result = 0.1 + 0.2;
	    expect(result).toBeCloseTo(0.3, 5); // Asserts that result is close to 0.3 within 5 decimal places
	  });
	});

String Matchers

String matchers are used to perform assertions on string values. We’ll look at the following matchers:

  • toMatch for checking if a string matches a regular expression or contains a substring
  • toContain for checking if a string contains a specific substring

3.1 toMatch

The toMatch matcher is used to check if a string matches a regular expression or a substring.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('String Matchers', () => {
	  it('should check if a string matches a regular expression using toMatch', () => {
	    const str = 'hello world';
	    expect(str).toMatch(/world/); // Asserts that str matches the regular expression /world/
	  });
	
	  it('should check if a string contains a substring using toMatch', () => {
	    const str = 'hello world';
	    expect(str).toMatch('world'); // Asserts that str contains the substring 'world'
	  });
	});

3.2 toContain

The toContain matcher is used to check if a string contains a specific substring.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('String Matchers', () => {
	  it('should check if a string contains a substring using toContain', () => {
	    const str = 'JavaScript is awesome';
	    expect(str).toContain('awesome'); // Asserts that str contains the substring 'awesome'
	  });
	});

Array and Iterable Matchers

Array and iterable matchers are used to perform assertions on arrays and iterable objects. In this chapter, we’ll cover some of the most commonly used array and iterable matchers in Vitest.

4.1 toContain

The toContain matcher is used to check if an array contains a specific item.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Array and Iterable Matchers', () => {
	  it('should check if an array contains a specific item using toContain', () => {
	    const arr = ['apple', 'banana', 'cherry'];
	    expect(arr).toContain('banana'); // Asserts that arr contains the item 'banana'
	  });
	});

4.2 toHaveLength

The toHaveLength matcher is used to check the length of an array or iterable object.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Array and Iterable Matchers', () => {
	  it('should check the length of an array using toHaveLength', () => {
	    const arr = ['apple', 'banana', 'cherry'];
	    expect(arr).toHaveLength(3); // Asserts that arr has a length of 3
	  });
	
	  it('should check the length of a string using toHaveLength', () => {
	    const str = 'Vitest';
	    expect(str).toHaveLength(6); // Asserts that str has a length of 6
	  });
	});

4.3 toContainEqual

The toContainEqual matcher is used to check if an array contains an object that matches a specified structure.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Array and Iterable Matchers', () => {
	  it('should check if an array contains an object with a specific structure using toContainEqual', () => {
	    const arr = [
	      { name: 'John', age: 30 },
	      { name: 'Jane', age: 25 }
	    ];
	    expect(arr).toContainEqual({ name: 'Jane', age: 25 }); // Asserts that arr contains an object with the structure { name: 'Jane', age: 25 }
	  });
	});

Object Matchers

Object matchers are used to perform assertions on objects. We’ll cover some of the most commonly used object matchers:

  • toHaveProperty for checking if an object has a specific property
  • toMatchObject for checking if an object matches a specified structure
  • toStrictEqual for deep equality checks of objects

5.1 toHaveProperty

The toHaveProperty matcher is used to check if an object has a specific property.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Object Matchers', () => {
	  it('should check if an object has a specific property using toHaveProperty', () => {
	    const obj = { name: 'John', age: 30 };
	    expect(obj).toHaveProperty('name'); // Asserts that obj has a property 'name'
	  });
	
	  it('should check if an object has a specific property with a value using toHaveProperty', () => {
	    const obj = { name: 'John', age: 30 };
	    expect(obj).toHaveProperty('age', 30); // Asserts that obj has a property 'age' with the value 30
	  });
	});

5.2 toMatchObject

The toMatchObject matcher is used to check if an object matches a specified structure.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Object Matchers', () => {
	  it('should check if an object matches a specified structure using toMatchObject', () => {
	    const obj = {
	      name: 'John',
	      age: 30,
	      address: { city: 'New York', zip: '10001' }
	    };
	    expect(obj).toMatchObject({
	      name: 'John',
	      address: { city: 'New York' }
	    }); // Asserts that obj matches the specified structure
	  });
	});

5.3 toStrictEqual

The toStrictEqual matcher is used for deep equality checks, ensuring that objects have the same structure and values, including nested objects and arrays.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Object Matchers', () => {
	  it('should check if objects are deeply equal using toStrictEqual', () => {
	    const obj1 = { name: 'John', age: 30, hobbies: ['reading', 'traveling'] };
	    const obj2 = { name: 'John', age: 30, hobbies: ['reading', 'traveling'] };
	    expect(obj1).toStrictEqual(obj2); // Asserts that obj1 is deeply equal to obj2
	  });
	});

Exception and Error Matchers

Exception and error matchers are used to handle and assert exceptions and errors in your tests. We’ll cover the most commonly used exception and error matchers.

  • toThrow for checking if a function throws an error
  • toThrowErrorMatchingSnapshot for checking if a function throws an error that matches a previously saved snapshot
  • toThrowErrorMatchingInlineSnapshot for checking if a function throws an error that matches an inline snapshot

6.1 toThrow

The toThrow matcher is used to check if a function throws an error.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Exception and Error Matchers', () => {
	  it('should check if a function throws an error using toThrow', () => {
	    const throwError = () => {
	      throw new Error('Something went wrong!');
	    };
	    expect(throwError).toThrow(); // Asserts that throwError throws an error
	  });
	
	  it('should check if a function throws a specific error using toThrow', () => {
	    const throwError = () => {
	      throw new Error('Something went wrong!');
	    };
	    expect(throwError).toThrow('Something went wrong!'); // Asserts that throwError throws an error with the specified message
	  });
	});

6.2 toThrowErrorMatchingSnapshot

The toThrowErrorMatchingSnapshot matcher is used to check if a function throws an error that matches a previously saved snapshot.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Exception and Error Matchers', () => {
	  it('should check if a function throws an error matching a snapshot using toThrowErrorMatchingSnapshot', () => {
	    const throwError = () => {
	      throw new Error('Snapshot error!');
	    };
	    expect(throwError).toThrowErrorMatchingSnapshot(); // Asserts that throwError throws an error matching the saved snapshot
	  });
	});

6.3 toThrowErrorMatchingInlineSnapshot

The toThrowErrorMatchingInlineSnapshot matcher is used to check if a function throws an error that matches an inline snapshot.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Exception and Error Matchers', () => {
	  it('should check if a function throws an error matching an inline snapshot using toThrowErrorMatchingInlineSnapshot', () => {
	    const throwError = () => {
	      throw new Error('Inline snapshot error!');
	    };
	    expect(throwError).toThrowErrorMatchingInlineSnapshot(`"Inline snapshot error!"`); // Asserts that throwError throws an error matching the inline snapshot
	  });
	});

Asynchronous Matchers

Asynchronous matchers are used to handle promises and async functions in your tests. In this chapter, we’ll cover the most commonly used asynchronous matchers in Vitest.

7.1 resolves / rejects

The resolves and rejects matchers are used to handle promises that resolve or reject.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Asynchronous Matchers', () => {
	  it('should handle a promise that resolves using resolves', async () => {
	    const fetchData = () => Promise.resolve('data');
	    await expect(fetchData()).resolves.toBe('data'); // Asserts that fetchData resolves with 'data'
	  });
	
	  it('should handle a promise that rejects using rejects', async () => {
	    const fetchData = () => Promise.reject(new Error('error'));
	    await expect(fetchData()).rejects.toThrow('error'); // Asserts that fetchData rejects with an error containing 'error'
	  });
	});

7.2 toResolve

The toResolve matcher is used to assert that a promise resolves.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Asynchronous Matchers', () => {
	  it('should assert that a promise resolves using toResolve', async () => {
	    const fetchData = () => Promise.resolve('data');
	    await expect(fetchData()).toResolve(); // Asserts that fetchData resolves
	  });
	});

7.3 toReject

The toReject matcher is used to assert that a promise rejects.

javascript
	// example.test.js
	import { describe, it, expect } from 'vitest';
	
	describe('Asynchronous Matchers', () => {
	  it('should assert that a promise rejects using toReject', async () => {
	    const fetchData = () => Promise.reject(new Error('error'));
	    await expect(fetchData()).toReject(); // Asserts that fetchData rejects
	  });
	});

Summary

In this lesson, we have explored various types of matchers available in Vitest and how they can be used to write effective and comprehensive tests for your JavaScript code.