Lab 13: Testing with Jest

Time: 30 minutes | Level: Practitioner | Docker: docker run -it --rm node:20-alpine sh

Overview

Master testing in JavaScript using Jest: describe/it/expect, matchers, mocks (jest.fn/jest.spyOn/jest.mock), async testing, and code coverage.


Step 1: Setup

cd /app && npm init -y
npm install --save-dev jest

# package.json
# "scripts": { "test": "jest", "test:coverage": "jest --coverage" }

Step 2: Basic Tests

// math.js
function add(a, b) { return a + b; }
function multiply(a, b) { return a * b; }
function divide(a, b) {
  if (b === 0) throw new RangeError('Division by zero');
  return a / b;
}
function factorial(n) {
  if (n < 0) throw new RangeError('n must be non-negative');
  if (n === 0 || n === 1) return 1;
  return n * factorial(n - 1);
}
module.exports = { add, multiply, divide, factorial };

// math.test.js
const { add, multiply, divide, factorial } = require('./math');

describe('add()', () => {
  it('adds two positive numbers', () => {
    expect(add(2, 3)).toBe(5);
  });
  it('handles negative numbers', () => {
    expect(add(-1, 1)).toBe(0);
  });
  it('handles floats', () => {
    expect(add(0.1, 0.2)).toBeCloseTo(0.3);
  });
});

describe('divide()', () => {
  it('divides correctly', () => {
    expect(divide(10, 2)).toBe(5);
  });
  it('throws on division by zero', () => {
    expect(() => divide(10, 0)).toThrow(RangeError);
    expect(() => divide(10, 0)).toThrow('Division by zero');
  });
});

describe('factorial()', () => {
  it.each([
    [0, 1], [1, 1], [5, 120], [10, 3628800]
  ])('factorial(%i) = %i', (n, expected) => {
    expect(factorial(n)).toBe(expected);
  });
});

Step 3: Matchers


Step 4: Mocking Functions


Step 5: jest.fn and jest.spyOn


Step 6: Async Testing


Step 7: Setup/Teardown and Coverage


Step 8: Capstone — Inline Jest Test

📸 Verified Output:


Summary

Jest API
Purpose

describe(name, fn)

Group related tests

test/it(name, fn)

Individual test case

expect(val).toBe(v)

Strict equality

expect(val).toEqual(v)

Deep equality

expect(fn).toThrow()

Expect thrown error

jest.fn()

Create mock function

jest.spyOn(obj, 'method')

Spy on existing method

jest.mock('module')

Auto-mock a module

.resolves/.rejects

Assert async promise

beforeAll/afterAll

Run once per suite

beforeEach/afterEach

Run around each test

Last updated