Unit tests are essential for increasing the test coverage of a backend application, ensuring its reliability, functionality, and robustness. Jest has become one of the most popular solutions when unit testing in Node, due to its intuitive API, zero-configuration philosophy, and flexible approach to code transpilation.
In this guide, you will learn more about Jest, explore its features, and see it in action through a complete example.
Become a Jest unit testing expert!
What Is Jest?
Jest is a free, open-source JavaScript testing framework that checks the correctness of your codebase. It is focused on simplicity with a zero-config approach. It works with backend applications built in Node.js as well as frontend applications in React, Angular, Vue, and more. When it comes to code transpilation, it integrates natively with Babel, Vite, Parcel, and webpack.
With Jest, you can write unit, integration, and snapshot tests in both JavaScript and TypeScript.
At the time of writing, Jest boasts over 44.3k stars on GitHub and over 30 million weekly downloads on npm. These impressive figures place Jest among the top testing libraries in the JavaScript ecosystem.
Exploring Jest: Features, Capabilities, and Core Aspects
Now that you know what Jest is, it's time to discover why it's so popular by analyzing its main features.
Intuitive API
By default, a Jest test is a JavaScript or TypeScript file with the .test.{js,jsx,ts,tsx}
or .spec.{js,jsx,ts,tsx}
extension.
Unless configured otherwise, Jest automatically looks for test files in the __tests__
directory or any sub-folder inside your project's root folder.
A single test file can contain more than one Jest unit test, as in the example below:
As you can tell, Jest follows a Behavior Driven Development (BDD)-like syntax that allows you to organize tests using these functions:
describe()
: Defines a group of related tests. This isn't required, but it helps organize tests into groups.test()
: Defines an individual test case. It accepts a name, a callback function containing the test logic, and an optional timeout value. This function is also available via theit()
alias.beforeAll()
: A hook that runs the specified function before any of the tests in the file. If the function returns aPromise
, Jest waits for thePromise
to resolve before running the tests.afterAll()
: Runs the given function after all the tests in the file have completed.beforeEach()
: Runs a function before each of the tests in the file is executed.afterEach()
: Runs the defined function after each one of the tests in the file completes.
Note that if any of the last four functions returns a Promise
, Jest waits for that Promise
to resolve before continuing.
Human-Readable Assertions
Jest unit testing is based on the AAA pattern:
- Arrange: Set up the conditions and prerequisites required for running the test (e.g., populating a demo database).
- Act: Execute the code to test, which usually boils down to calling a single function.
- Assert: Verify that the results match your expectations.
The Jest BDD-like interface presented earlier enables you to cover the first two steps of this pattern.
To address the last one, Jest provides a complete assertion engine called expect()
.
This global function is used to check that values in a test meet certain conditions.
With almost 40 million weekly downloads, expect
is the most popular JavaScript assertion library.
expect()
accepts a value, and is then followed by some modifiers and matchers:
- Modifiers: Alter the checking process. The most popular modifier function is
not()
. - Matchers: Validate that the value meets specific conditions. Popular matcher functions include
toBe()
,toEqual()
,toBeTruthy()
,toBeFalsy()
,toContain()
,toHaveLength()
, andtoThrow()
.
By chaining these functions, you can define human-readable and easy-to-maintain assertions, as follows:
Additional Jest matchers can be found in the community-driven jest-extended
project.
High Configurability
The design philosophy of Jest emphasizes working seamlessly out of the box in most scenarios while offering extensive customization options to meet diverse needs.
The official documentation particularly recommends defining a dedicated Jest configuration file. This can be a JavaScript, TypeScript, or JSON file, automatically detected when named jest.config.js|ts|mjs|cjs|json
. Alternatively, you can manually specify the configuration file using the --config
CLI flag.
The Jest configuration file must define an object containing all your custom configurations:
There are more than 70 options available, including:
collectCoverage
: Indicates whether the test coverage information should be collected and reported in the output.errorOnDeprecated
: Ensures that calling deprecated APIs triggers useful error messages, simplifying the process of identifying and addressing outdated code during upgrades.maxConcurrency
: Specifies the number of tests that are allowed to run at the same time when usingtest.concurrent()
, an experimental version oftest()
to run tests concurrently.testMatch
: Specifies an array of glob patterns that Jest uses to detect test files in your project.verbose
: Indicates whether each individual test should be reported during the run.
See all available options in the Jest documentation.
Mocks for Functions, Classes, and Node.js Modules
Mocking is a technique used in testing to replace a component with a simplified version that mimics the behavior of the original. The idea is to isolate the code you are testing, simulating all its dependencies with controlled mocks.
Jest comes with robust mocking capabilities, supporting:
- Mock functions: Also known as spies, they enable you to monitor and control the behavior of functions called indirectly by other code. You can define mock functions with the
jest.fn()
method. - Node modules: To mock entire Node.js modules, such as
lodash
orfs
. Jest also supports mocking user-defined JavaScript modules. - ES6 class mocks: Mock ES6 classes imported into the files under test. Since ES6 classes are essentially constructor functions, you can mock them using either mock functions or actual ES6 classes.
This mocking functionality gives you the ability to create more focused and effective Jest unit test functions.
Dedicated Visual Studio Code Extension
Jest supports vscode-jest
, a dedicated extension that makes testing more intuitive and enjoyable in VS Code.
The extension, simply called “Jest” in the VS Code marketplace, is maintained by the Jest community.
It works out of the box for most common Jest projects and supports all Jest features.
To get started with it, install the "Jest" extension in Visual Studio Code and reload the IDE.
If the extension finds the global jest
command, it will automatically run and monitor all your tests. You can now execute tests and see their status, errors, and coverage, as shown in the image below:
Integrating Jest into Node.js for Unit Testing
Let's learn how to set up Jest for unit testing in Node.js.
Introducing the Node.js Project
Suppose you already have a Node.js project in place, and you want to add some Jest unit tests to it.
Let's assume your project has a utils
folder containing a math.js
file that exports the following pow()
function:
This is just a custom implementation of the exponentiation mathematical operation.
Your goal is to write some unit tests in Jest to ensure the pow()
function works as desired.
Setting Up Jest
Install Jest by adding the jest
npm package to your project’s development dependencies:
Otherwise, you can install it globally in your system with the command below:
Then, add a jest.config.js
configuration file in the root folder of your project to enable verbose mode:
As a final step, make sure the scripts
section of your package.json
file contains a test
command to launch Jest:
Wonderful! You just set up Jest in Node.js for unit testing.
Defining a Unit Test
The official Jest documentation recommends adding unit tests directly to the folder that holds your code for testing. This keeps your tests organized and easily accessible alongside the code they are testing.
So, add a math.test.js
inside the utils
folder of your Node project and initialize it with the following logic:
As you can see, this test file contains five different unit tests to check the behavior of the pow()
function in different situations.
Your utils
folder will now contain these two files:
Note that Visual Studio Code marks .test.js
files with a different icon to distinguish them from the source code.
Amazing! All that remains is to launch the Jest tests and verify that they work.
Running a Test
You can launch Jest locally with this command:
Or if you defined the test
script in package.json
as mentioned earlier, run:
Otherwise, if you installed Jest globally, launch your tests with the command below in the root folder of your project:
Regardless of the approach you take to executing Jest tests, the result will be something like this:
Since our Node.js project only contains the math.test.js
test file, Jest will execute only that.
It runs all the unit tests defined within math.test.js
, ensuring that each test produces the expected results (as specified in the test assertions).
Et voilà! You now know how to write unit tests with Jest in Node.js.
Next Steps For Mastering Jest
Next, you should learn how to integrate Jest with your CI/CD pipeline to automate your testing process.
To become proficient with Jest, explore its comprehensive documentation and GitHub repository. You'll find tons of examples and Jest troubleshooting tips. Additionally, the documentation includes a section with useful resources, such as the Jest Discord channel, where you can connect with the community for support and advice.
Wrapping Up
In this blog post, we explored what Jest is and how it simplifies writing unit tests in your Node.js application.
You now know:
- What Jest is
- The main features it provides when it comes to testing
- How to define unit tests in Node.js with Jest
Thanks for reading!
P.S. If you liked this post, subscribe to our JavaScript Sorcery list for a monthly deep dive into more magical JavaScript tips and tricks.
P.P.S. If you need an APM for your Node.js app, go and check out the AppSignal APM for Node.js.