← JS Mastery | Module 10: Advanced Patterns Testing with Jest: Unit & Integration Tests
Module 10

Testing with Jest: Unit & Integration Tests

⏱ 26 min read ● Advanced 🆓 Free

Setting Up Jest

// npm install -D jest @jest/globals
// Add to package.json: "test": "jest"

// Write a test:
// math.test.js
import { add, divide } from "./math.js";

describe("Math module", () => {
  describe("add()", () => {
    test("adds two positive numbers", () => {
      expect(add(2, 3)).toBe(5);
    });
    
    test("adds negative numbers", () => {
      expect(add(-1, -2)).toBe(-3);
    });
    
    test("adds zero", () => {
      expect(add(5, 0)).toBe(5);
    });
  });
  
  describe("divide()", () => {
    test("divides correctly", () => {
      expect(divide(10, 2)).toBe(5);
    });
    
    test("throws on division by zero", () => {
      expect(() => divide(10, 0)).toThrow("Division by zero");
    });
  });
});

Jest Matchers

// Common matchers:
expect(value).toBe(5);                    // strict equality ===
expect(value).toEqual({ a: 1 });          // deep equality
expect(value).toBeTruthy();               // truthy
expect(value).toBeFalsy();                // falsy
expect(value).toBeNull();                 // null
expect(value).toBeUndefined();            // undefined
expect(value).toBeDefined();              // not undefined
expect(arr).toContain("item");            // array contains
expect(str).toContain("substr");          // string contains
expect(num).toBeGreaterThan(5);           // > 5
expect(num).toBeLessThanOrEqual(10);      // <= 10
expect(arr).toHaveLength(3);              // array.length === 3
expect(fn).toThrow("error message");      // function throws
expect(fn).toThrowError(TypeError);       // throws specific type

// Async tests:
test("fetches user", async () => {
  const user = await fetchUser(1);
  expect(user).toHaveProperty("name");
  expect(user.id).toBe(1);
});

// Before/After hooks:
beforeEach(() => {
  // runs before each test
  db.clear();
});

afterAll(async () => {
  // runs after all tests in file
  await db.close();
});

Mocking

// Mock a module:
jest.mock("./db", () => ({
  getUser: jest.fn().mockResolvedValue({ id: 1, name: "Alice" }),
  saveUser: jest.fn().mockResolvedValue(true)
}));

// Mock a function:
const mockFn = jest.fn();
mockFn.mockReturnValue(42);
mockFn.mockResolvedValue({ data: [] });  // async

// Verify calls:
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledTimes(2);
expect(mockFn).toHaveBeenCalledWith("arg1", "arg2");

// Spy on existing methods:
const spy = jest.spyOn(console, "log");
doSomething();
expect(spy).toHaveBeenCalledWith("expected message");
spy.mockRestore();

⚡ Key Takeaways

🎯 Practice Exercises

EXERCISE 1

Write unit tests for a Calculator class: add, subtract, multiply, divide methods. Achieve 100% coverage including error cases. Use describe/test structure.

EXERCISE 2 — CHALLENGE

Write integration tests for your Express REST API: test each endpoint with supertest. Mock the database. Test success cases and error cases (404, 400, 409).

← TypeScript Intro