100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Node.js

Testing Node Apps with Jest

Learn to write unit and integration tests for Node.js and Express apps using Jest and Supertest.

Testing & DebuggingIntermediate12 min readJul 8, 2026
Analogies

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

javascript
// 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

javascript
// 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

Was this page helpful?

Topics covered

#NodeJs#NodeJsExpressStudyNotes#WebDevelopment#TestingNodeAppsWithJest#Testing#Node#Apps#Jest#StudyNotes#SkillVeris