Manuals / JavaScript / Ch 10

D · Modules & TestingIntermediate50 min read

10. Unit testing with Vitest

JavaScript · 56 pages source format

Tests encode expectations so refactors do not break behavior. Vitest is fast, Vite-native, Jest-compatible. Arrange-Act-Assert. Test pure functions first. Mock fetch for API modules. Coverage is a guide, not a goal.

What you'll learn

  • Vitest setup
  • describe/it/expect
  • Testing pure functions
  • Mocking fetch
  • Test-driven habit

Install Vitest

npm install -D vitest. Add "test": "vitest" to package.json scripts. Co-locate tests as *.test.js or in __tests__/.

npm install -D vitest

// package.json
"scripts": { "test": "vitest", "test:run": "vitest run" }

Do this now

Add Vitest to your Vite project. Write one passing test to verify setup.

Clear?

First tests

describe groups tests. it (or test) is one case. expect(value).toBe(expected) for primitives, .toEqual for objects/arrays.

import { describe, it, expect } from "vitest"
import { titleCase } from "./utils.js"

describe("titleCase", () => {
  it("capitalizes each word", () => {
    expect(titleCase("hello world")).toBe("Hello World")
  })
  it("returns empty for empty input", () => {
    expect(titleCase("")).toBe("")
  })
})

Do this now

Test titleCase: normal input, empty string, single word, multiple spaces.

Clear?

Test edge cases

Empty, null-ish, boundary values, error paths. Tests document intended behavior for the next reader.

  • Happy path — typical input
  • Empty input
  • Single item
  • Invalid input (if applicable)
  • Boundary values

Do this now

Add 5+ tests for your data transformer from the arrays chapter.

Clear?

Mock fetch

vi.fn() and global.fetch = vi.fn() for API tests. Return mock Response with ok and json(). Reset mocks in beforeEach.

import { vi } from "vitest"

vi.stubGlobal("fetch", vi.fn())

fetch.mockResolvedValue({
  ok: true,
  json: () => Promise.resolve({ title: "Test" }),
})

Do this now

Test getPost(id) with mocked fetch returning fake JSON and throwing on 404.

Clear?

When to test

Always: pure business logic, parsers, validators. Sometimes: integration with mocked I/O. Rarely: DOM (use E2E tools later).

Do this now

Aim for 10+ tests across utils and api modules. npm run test:run green.

Pro tip. Red-green-refactor: write failing test, make it pass, clean up.

Clear?

Checklist