Node.js9 min read

Testing Node.js with Jest

Write tests for Node.js applications using Jest. Learn unit tests, mocking, and testing async code.

Sarah Chen
December 19, 2025
0.0k0

Testing Node.js with Jest

Jest is the most popular testing framework. Simple, fast, feature-rich.

Setup

npm install --save-dev jest
// package.json
{
  "scripts": {
    "test": "jest",
    "test:watch": "jest --watch"
  }
}

First Test

// math.js
function add(a, b) {
  return a + b;
}
module.exports = { add };

// math.test.js
const { add } = require('./math');

test('adds 1 + 2 to equal 3', () => {
  expect(add(1, 2)).toBe(3);
});

Run: npm test

Common Matchers

// Equality
expect(2 + 2).toBe(4);
expect({ name: 'Alice' }).toEqual({ name: 'Alice' });

// Truthiness
expect(null).toBeNull();
expect(undefined).toBeUndefined();
expect(true).toBeTruthy();
expect(false).toBeFalsy();

// Numbers
expect(4).toBeGreaterThan(3);
expect(4).toBeLessThan(5);
expect(0.1 + 0.2).toBeCloseTo(0.3);

// Strings
expect('team').toMatch(/tea/);

// Arrays
expect(['Alice', 'Bob']).toContain('Alice');

// Exceptions
expect(() => throwError()).toThrow();
expect(() => throwError()).toThrow('error message');

Grouping Tests

describe('Math functions', () => {
  describe('add', () => {
    test('adds positive numbers', () => {
      expect(add(1, 2)).toBe(3);
    });
    
    test('adds negative numbers', () => {
      expect(add(-1, -2)).toBe(-3);
    });
  });
  
  describe('multiply', () => {
    test('multiplies numbers', () => {
      expect(multiply(2, 3)).toBe(6);
    });
  });
});

Testing Async Code

// With async/await
test('fetches user', async () => {
  const user = await fetchUser(1);
  expect(user.name).toBe('Alice');
});

// With promises
test('fetches user', () => {
  return fetchUser(1).then(user => {
    expect(user.name).toBe('Alice');
  });
});

// With done callback
test('fetches user', (done) => {
  fetchUser(1, (user) => {
    expect(user.name).toBe('Alice');
    done();
  });
});

Mocking

// Mock function
const mockFn = jest.fn();
mockFn('hello');

expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledWith('hello');
expect(mockFn).toHaveBeenCalledTimes(1);

// Mock return value
const mockFn = jest.fn().mockReturnValue(42);
expect(mockFn()).toBe(42);

// Mock async
const mockAsync = jest.fn().mockResolvedValue({ id: 1 });
await mockAsync();

Mocking Modules

// Mock entire module
jest.mock('./database');
const db = require('./database');

db.query.mockResolvedValue([{ id: 1, name: 'Alice' }]);

test('gets users from database', async () => {
  const users = await getUsers();
  expect(users).toHaveLength(1);
});

Testing Express Routes

const request = require('supertest');
const app = require('./app');

describe('GET /api/users', () => {
  test('returns users', async () => {
    const response = await request(app)
      .get('/api/users')
      .expect('Content-Type', /json/)
      .expect(200);
    
    expect(response.body).toBeInstanceOf(Array);
  });
});

describe('POST /api/users', () => {
  test('creates user', async () => {
    const response = await request(app)
      .post('/api/users')
      .send({ name: 'Alice', email: 'alice@example.com' })
      .expect(201);
    
    expect(response.body.name).toBe('Alice');
  });
  
  test('returns 400 for invalid data', async () => {
    await request(app)
      .post('/api/users')
      .send({ name: '' })
      .expect(400);
  });
});

Setup and Teardown

describe('User tests', () => {
  beforeAll(async () => {
    // Run once before all tests
    await connectDB();
  });
  
  afterAll(async () => {
    // Run once after all tests
    await disconnectDB();
  });
  
  beforeEach(async () => {
    // Run before each test
    await clearDatabase();
  });
  
  afterEach(() => {
    // Run after each test
    jest.clearAllMocks();
  });
  
  test('test 1', () => { ... });
  test('test 2', () => { ... });
});

Coverage

npm test -- --coverage
// package.json
{
  "jest": {
    "collectCoverageFrom": ["src/**/*.js"],
    "coverageThreshold": {
      "global": {
        "branches": 80,
        "functions": 80,
        "lines": 80
      }
    }
  }
}

Key Takeaway

Jest makes testing easy. Use describe to group tests, test for individual cases. Mock external dependencies. Test Express routes with supertest. Aim for high coverage but focus on meaningful tests.

#Node.js#Testing#Jest#Quality#Intermediate