Introduction
Jest is a popular JavaScript testing framework that provides a test runner, assertion library, and mocking utilities out of the box. In Node.js and Express applications, Jest is commonly used to write unit tests for individual functions and integration tests for API endpoints, helping catch bugs before code reaches production.
Cricket analogy: Jest is like a full match-review system providing a video replay operator, a rulebook for decisions, and a practice bowling machine all in one kit; teams use it to run net sessions testing individual shots (unit tests) and full simulated matches testing the whole batting lineup (integration tests) before the real tournament.
Syntax
// math.js
function add(a, b) {
return a + b;
}
module.exports = { add };
// math.test.js
const { add } = require('./math');
describe('add function', () => {
it('should add two numbers correctly', () => {
expect(add(2, 3)).toBe(5);
});
it('should handle negative numbers', () => {
expect(add(-1, -1)).toBe(-2);
});
});Explanation
The describe() block groups related tests together, while it() (or test()) defines an individual test case. expect() wraps the value under test and is chained with matchers like toBe(), toEqual(), or toThrow() to make assertions. Jest also provides jest.fn() to create mock functions and jest.mock() to mock entire modules, which is essential for isolating units of code from dependencies like databases or external APIs. For testing Express routes end-to-end, the supertest library lets you make simulated HTTP requests against your app without starting a real server.
Cricket analogy: The describe() block groups related net sessions together, like grouping all batting drills under one practice plan, while it() defines one specific drill; expect() is the coach's evaluation of a shot, chained with matchers like 'clean hit' or 'edged' to judge outcomes, and jest.fn() creates a stand-in bowler to test a batter's reaction without a real match, mirroring how supertest lets you simulate a full over without playing an actual game.
Example
// app.js
const express = require('express');
const app = express();
app.use(express.json());
app.get('/api/users/:id', (req, res) => {
if (req.params.id === '1') {
return res.status(200).json({ id: 1, name: 'Ada' });
}
return res.status(404).json({ error: 'User not found' });
});
module.exports = app;
// app.test.js
const request = require('supertest');
const app = require('./app');
describe('GET /api/users/:id', () => {
it('returns user data for a valid id', async () => {
const res = await request(app).get('/api/users/1');
expect(res.statusCode).toBe(200);
expect(res.body).toEqual({ id: 1, name: 'Ada' });
});
it('returns 404 for an unknown id', async () => {
const res = await request(app).get('/api/users/99');
expect(res.statusCode).toBe(404);
});
});
// Mocking a dependency
const db = require('./db');
jest.mock('./db');
test('mocked db call returns fake data', async () => {
db.findUser.mockResolvedValue({ id: 2, name: 'Grace' });
const user = await db.findUser(2);
expect(user.name).toBe('Grace');
expect(db.findUser).toHaveBeenCalledWith(2);
});Output
Running npx jest executes all files matching *.test.js or inside a __tests__ folder. Jest prints a summary showing PASS or FAIL per file, the number of tests passed/failed, and total execution time. Failed assertions show a diff between the expected and received values, making it easy to pinpoint what went wrong.
Cricket analogy: Running npx jest is like the review official checking every recorded delivery matching a set pattern (*.test.js or __tests__); the printed scorecard shows PASS or FAIL per over, the total deliveries reviewed, and elapsed time, and a failed decision shows a clear side-by-side comparison of what was expected versus what actually happened, pinpointing the missed call.
Key Takeaways
- describe() groups tests; it()/test() defines a single test case; expect() makes assertions with matchers.
- jest.fn() and jest.mock() isolate units of code by mocking dependencies such as database calls.
- supertest integrates with Jest to test Express routes and HTTP responses without a live server.
- Async route handlers should be tested with async/await inside test functions to properly await responses.
Practice what you learned
1. Which Jest function is used to group related test cases together?
2. What library is commonly paired with Jest to test Express HTTP endpoints?
3. Which Jest API creates a mock function to track calls and control return values?
4. What matcher would you use to assert that two objects are deeply equal in Jest?
Was this page helpful?
You May Also Like
Debugging Node.js Applications
Learn to debug Node.js apps using the built-in inspector, console methods, and Chrome DevTools.
Logging in Node.js Apps
Learn why console.log is insufficient in production and how to implement structured logging with Winston or Pino.
Error Handling in Express
Master synchronous and asynchronous error handling in Express using 4-argument error middleware.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics