Jest – Using Matchers
By Mohit Joshi, Community Contributor - December 26, 2024
Jest is an open-source JavaScript-based testing framework that supports Angular, React, Vue, Babel, TypeScript projects, and more. The primary purpose of implementing Jest is to ease the process of testing complex web applications. It works out-of-the-box for many front-end frameworks by significantly reducing the configuration time and complexities.
Jest extends its support to test any JavaScript-based codebase. It doesn’t rely heavily on third-party services, which makes it a reliable option offering a straightforward handy operation.
- What are Jest Matchers?
- Importance of Jest Matchers
- Types of Jest Matchers
- 1. .toBe(value)
- 2. .toBeCloseTo(number, numDigits?)
- 3. .toBeDefined()
- 4. .toBeUndefined()
- 5. .toBeNull()
- 6. .toBeTruthy()
- 7. .toBeFalsy()
- 8. .toBeGreaterThan()
- 9. .toMatch()
What are Jest Matchers?
Jest Matchers are methods provided in the Jest to assert the test cases of our project. These assertions are very useful in ensuring the output of the code in the script matches the intended result.
The primary reasons for using Matchers could be that they enhance the readability of the test scripts and assert a variety of test cases, ranging from basic tests to exceptions.
For example, a function that processes user input and delivers an output can be tested using Jest Matchers like toEqual() to verify the output matches the expected result.
Read More: How to debug Jest tests?
Here is a brief example to understand how Jest Matchers works.
In this example, a simple addition function returns the sum of two input values. Matchers like toBe() and not.toBe() can be used to assert the function’s output against the intended result.
addition.js
function add(a, b) { return a + b; } module.exports = add;
addition.test.js
const add = require('./addition'); test("add function adds two numbers correctly", () => { expect(add(2, 3)).toBe(5); expect(add(2, 3)).not.toBe(6); });
- toBe: Verifies the function returns the exact expected value.
- not.toBe: Ensures the output is not an incorrect value.
Importance of Jest Matchers
Jest Matchers helps developers write effective yet readable code scripts. It enhances the codebase’s maintainability and offers several methods to ensure the correctness of its code and validate it in different scenarios.
- Jest Matchers enhances the code readability and makes it easy to comprehend by using simpler syntax.
Here’s an example of a clear and concise assertion.
expect(result).toBe(42);
- It enhances collaboration among team members by ensuring consistent testing practices across the project that are easy for several people to comprehend, thus allowing active value addition among peers.
- For failed tests, Jest Matchers provides detailed error messages locating precisely which Matcher failed and the reason for failure. This process reduces the project’s overall debugging time, thus boosting efficiency.
- There are several types of Matchers. Thus, it covers many assertions, including basic equality, testing the specific state of values, numerical assertions, validating textual data, and much more.
Also Read: Top Javascript Testing Frameworks
Types of Jest Matchers
There are several types of Jest Matchers based on the manner of assertions they perform. Understanding the various types is important to carefully picking the right Matcher for the appropriate job.
1. .toBe(value)
This Matcher asserts the strict equality between the actual value and the expected value without any conversion. It is used for primitive types like numbers, strings, or booleans.
Example
test("checks strict equality using .toBe()", () => { expect("hello").toBe("hello"); // Passes expect(true).toBe(true); // Passes expect(2).toBe("2"); // Fails because 2 !== "2" });
It uses strict equality. Therefore, in the above example, 2 is not equal to “2”.
2. .toBeCloseTo(number, numDigits?)
This Matcher compares decimal numbers, ensuring the two are approximately equal within certain decimal places.
The Syntax is as follows:
.toBeCloseTo(number, numDigits?)
The numDigits parameter specifies the number of decimal places for the comparison. By default, it compares up to 2 decimal places.
Example
test("fails when numbers differ beyond the precision", () => { expect(0.12345).toBeCloseTo(0.124, 3); // Fails (they differ beyond 3 decimal places) expect(0.12345).toBeCloseTo(0.123, 3); // Passes (compares up to 3 decimal places) });
3. .toBeDefined()
This Matcher ensures the value of the variable or property is defined regardless of the value. It asserts if the function or variable is defined or undefined.
Example
test("checks that a variable is defined", () => { const value = "Hello World"; expect(value).toBeDefined(); // Passes }); test("checks that a variable is not undefined", () => { let value; expect(value).toBeDefined(); // Fails });
4. .toBeUndefined()
This Matcher ensures the value of the variable or property is undefined in all the scenarios.
Example
test("checks that a variable is undefined", () => { const value = "Hello World"; expect(value).toBeUndefined(); // Fails }); test("checks that a variable is not defined", () => { let value; expect(value).toBeUndefined(); // Passes });
5. .toBeNull()
This Matcher ensures that a function, property, or variable’s value is set explicitly to null, not even undefined, false, or 0.
Example
test("checks that a variable is null", () => { const value = null; expect(value).toBeNull(); // Passes });
6. .toBeTruthy()
This matcher is used to assert that a value is Truthy in all scenarios.
Example
test("checks that a variable is truthy", () => { expect(true).toBeTruthy; // Passes expect(1).toBeTruthy; // Passes });
7. .toBeFalsy()
This matcher is used to assert that a value is Falsy in all scenarios.
Example
test("checks that a value is falsy", () => { expect(false).toBeFalsy(); // Passes expect(0).toBeFalsy(); // Passes expect("").toBeFalsy(); // Passes expect(null).toBeFalsy(); // Passes expect(undefined).toBeFalsy(); // Passes expect(NaN).toBeFalsy(); // Passes });
Truthy vs. Falsy Values
A Truthy value or expression in JavaScript is a value that is considered true in the boolean context. On the other hand, a Falsy value is considered false in the boolean context.
The following values are considered falsy:
- false
- 0
- -0
- “”
- null
- undefined
- NaN
All other values are considered Truthy.
8. .toBeGreaterThan()
This Matcher ensures that the actual value is strictly greater than the expected value or vice versa.
Example
test("checks that a number is greater than a threshold", () => { const result = 10; expect(result).toBeGreaterThan(5); // Passes });
9. .toMatch()
This Matcher is used to ensure that the actual string strictly matches the expected string.
Example
test('string contains a substring', () => { expect('Hello, world!').toMatch('world'); // Passes });
How to Use Jest Matchers
In a JavaScript project, Matchers do not need to be imported manually, as Jest automatically includes them in the test file. Jest Matchers can be better understood through a typical example.
Before diving into an example, here is the general syntax for using any Matcher in a Jest test.
expect(actualValue).matcher(expectedValue);
- actualValue: The value your code produces.
- matcher: A Jest function (e.g., .toBe(), .toEqual(), .toMatch()).
- expectedValue: The value you expect.
Prerequisites
- You must have Node.Js installed on your system at least version 14 or higher.
- Install any IDE of your choice. This example is using Visual Studio Code IDE.
- You must be familiar with the basic concepts of JavaScript.
Setting up Project
1. Create a project folder and initialize a Node.js project using the following command in the terminal.
npm init -y
The above command will create a package.json file in the project directory.
2. Install Jest as a development dependency.
npm install --save-dev jest
3. Inside the package.json file, update the scripts section to include Jest.
"scripts": { "test": "jest" }
Writing the Jest Test
Here’s a simple test to demonstrate how Matchers work.
test('demonstrating Jest matchers', () => { const number = 42; const floatNumber = 42.0001; const string = 'Hello World’; const definedValue = 'I am defined'; const undefinedValue = undefined; const nullValue = null; const truthyValue = true; const falsyValue = 0; const greaterThanValue = 100; // Strict equality expect(number).toBe(42); // Passes // Approximate equality expect(floatNumber).toBeCloseTo(42, 3); // Passes // Defined and undefined expect(definedValue).toBeDefined(); // Passes expect(undefinedValue).toBeUndefined(); // Passes // Null checks expect(nullValue).toBeNull(); // Passes // Truthy and falsy values expect(truthyValue).toBeTruthy(); // Passes expect(falsyValue).toBeFalsy(); // Passes // Comparison expect(greaterThanValue).toBeGreaterThan(50); // Passes // String matching expect(string).toMatch(/hello/i); // Passes });
Run the Jest Test
Run the test by executing the following command in your terminal.
npm test
Output:
Best Practices for Using Jest Matchers
Following some standard practices is a good approach to writing a maintainable, readable, less flaky, and highly efficient codebase.
Here are some of the best practices to boost their efficiency.
- Use descriptive test names that clearly describe the purpose of the test. This approach helps others comprehend the intent of your test, thus boosting valuable collaboration.
- Use the most specific Matcher in your Jest script. This helps identify the exact issue in case a test fails, thus making the debugging process more efficient. Moreover, using a highly specific matcher ensures your test’s clear intent and provides a detailed yet essential error message when the test fails.
- One of the most efficient approaches is to avoid over-testing by focusing on what the code does instead of how it does, writing a single test instead of several overlapping ones, and avoiding testing things that are guaranteed by JavaScript, such as the push method of the array. Moreover, one should avoid code duplication to reduce flakiness in test results.
- Another practice for maintaining reliable tests is to run tests in isolation so that each test case gives output without any influence of other tests. It also facilitates parallel execution, which would otherwise be a failure due to the shared state of several elements within the test.
How to run tests using Jest on BrowserStack’s Selenium Grid
Jest has been successful in becoming more than just a testing tool and has found a place as a crucial element in the developer’s toolkit.
Therefore, by combining the power of Jest’s testing framework with BrowserStack’s cloud infrastructure, one can create highly scalable tests with cross-browser testing compatibility.
BrowserStack Automate provides features such as Parallel testing where one can test their application across numerous device and operating system combinations at once without relying upon physical devices.
Here’s how you can run tests using Jest on BrowserStack’s Selenium Grid:
Step 1: Pick any project of your choice or clone a sample project using the following command.
git clone https://github.com/browserstack/jest-js-browserstack.git Cd jest-js-browserstack npm install
Step 2: Obtain your BrowserStack credentials from the BrowserStack Profile. Replace the username and accesskey obtained in the browserstack.yml file.
Step 3: The browserstack.yml file configures the device and browser combinations. Here’s the sample file you can use for your project, which has three parallel threads configured.
userName: #enter username here accessKey: #enter accesskey here platforms: - os: Windows osVersion: 10 browserName: Chrome browserVersion: 120.0 - os: OS X osVersion: Monterey browserName: Safari browserVersion: 15.6 - deviceName: iPhone 13 osVersion: 15 browserName: Chromium deviceOrientation: portrait parallelsPerPlatform: 1 browserstackLocal: true buildName: browserstack-build-1 projectName: BrowserStack Sample debug: false networkLogs: false consoleLogs: errors
Step 4: To run the test, use the following command from the root directory of your project.
npm run sample-test
Once the test is executed, you can view the results from the Automate dashboard.
Conclusion
Jest is a JavaScript testing framework that ensures applications work as intended. It includes built-in Matchers for creating assertions without needing imports.
Jest Matchers improve test readability and provide detailed error messages, making debugging easier. Understanding and selecting the right Matcher enhances test quality.
To execute Jest Tests on Selenium Grid, you can rely on BrowserStack Automate. It not only provides a parallel execution feature that allows you to run several tests on different combinations of devices in the cloud at once but also provides ample device browser combinations that maximizes test coverage.
Useful Resources for Jest
- How to Debug Jest Tests?
- Understanding Jest Mock Hook
- How to Configure Jest
- it.each function in Jest
- Snapshot Testing with Jest
- How to write Snapshot Tests for React Components with Jest?
- How to Run Jest Tests for a Specific File/Folder
- Jest Framework Tutorial: How to use it?
- Understanding Testing Library Jest DOM
- Understanding Jest-Globals
- Unit Testing of React Apps using JEST : Tutorial
- How to test React App using Jest
- Understanding Jest beforeEach Function
- Performing NodeJS Unit testing using Jest
- Jest vs Mocha: Comparing NodeJS Unit Testing Frameworks
- Jest vs Mocha vs Jasmine: Which JavaScript framework to choose?