How do you write a unit test for a JavaScript function using Jest?
Jest is a popular JavaScript testing framework developed by Facebook, widely used for testing React components, Node.js applications, and other JavaScript projects. It's known for its simplicity, speed, and comprehensive feature set, including built-in assertion libraries, mocking capabilities, and excellent reporting.
Setting Up Jest
First, you need to create a new Node.js project (if you don't have one) and install Jest as a development dependency. Open your terminal in your project directory and run the following commands:
npm init -y
npm install --save-dev jest
You might also want to add a test script to your package.json for convenience:
{
"name": "my-js-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "jest"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"jest": "^29.0.0"
}
}
Writing Your First Test
Let's say you have a simple JavaScript function that adds two numbers. Create a file named sum.js:
// sum.js
function sum(a, b) {
return a + b;
}
module.exports = sum;
Now, create a test file for this function. Jest automatically looks for files ending with .test.js, .spec.js, or files in a __tests__ directory. Let's create sum.test.js in the same directory:
// sum.test.js
const sum = require('./sum');
describe('sum function', () => {
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
test('adds 0 + 0 to equal 0', () => {
expect(sum(0, 0)).toBe(0);
});
test('adds negative numbers correctly', () => {
expect(sum(-1, -2)).toBe(-3);
});
test('handles floating point numbers', () => {
expect(sum(0.1, 0.2)).toBeCloseTo(0.3); // Use toBeCloseTo for floating points
});
});
In this test file:
require('./sum')imports the function we want to test.describe('sum function', ...)is used to group related tests. It takes a string description and a callback function.test('adds 1 + 2 to equal 3', ...)(orit(...)) defines an individual test case. It also takes a description and a callback.expect(sum(1, 2))creates an assertion object for the result ofsum(1, 2).toBe(3)is a 'matcher' that checks if the received value is strictly equal to the expected value. Jest provides many other matchers liketoEqual,not.toBe,toBeTruthy,toThrow, etc.
Running Your Tests
To run your tests, you can use the command line directly or leverage the script defined in package.json:
# Using npx (recommended for one-off runs or CI)
npx jest
# Or if you set up the 'test' script in package.json
npm test
Jest will execute the tests, display the results in your console, indicating whether tests passed or failed, and provide details for any failures.
Common Jest Matchers
| Matcher | Description | Example |
|---|---|---|
| `toBe(value)` | Checks for strict equality (`===`). | `expect(2 + 2).toBe(4);` |
| `toEqual(value)` | Recursively checks equality of all fields of an object or array. | `expect({a: 1}).toEqual({a: 1});` |
| `toBeTruthy()` | Checks if a value is truthy. | `expect(true).toBeTruthy();` |
| `toBeFalsy()` | Checks if a value is falsy. | `expect(false).toBeFalsy();` |
| `toHaveBeenCalled()` | Checks if a mock function was called. | `expect(mockFn).toHaveBeenCalled();` |
| `toThrow(error?)` | Checks if a function throws an error. | `expect(() => mightThrow()).toThrow();` |
| `not.matcher()` | Negates any matcher. | `expect(value).not.toBe(otherValue);` |
Setup and Teardown
Jest provides hooks for performing setup and teardown before and after tests:
beforeEach(callback): Runs before each test in adescribeblock.afterEach(callback): Runs after each test in adescribeblock.beforeAll(callback): Runs once before all tests in adescribeblock.afterAll(callback): Runs once after all tests in adescribeblock.
let users = [];
describe('User management', () => {
beforeEach(() => {
// Initialize users array before each test
users = [{ id: 1, name: 'Alice' }];
});
test('should add a new user', () => {
users.push({ id: 2, name: 'Bob' });
expect(users.length).toBe(2);
});
test('should find a user by id', () => {
const user = users.find(u => u.id === 1);
expect(user).toEqual({ id: 1, name: 'Alice' });
});
});
By following these steps, you can effectively write and run unit tests for your JavaScript functions using Jest, ensuring the reliability and correctness of your codebase.