Testing Node.js Applications

1. Using Node Test Runner (node:test)

Example: Built-in v18+ stable

import { test, describe } from "node:test";
import assert from "node:assert/strict";
describe("math", () => {
  test("adds", () => assert.equal(1 + 2, 3));
});

2. Writing Test Suites

APIUse
describe(name, fn)Group tests
test(name, fn) / it(...)Individual test
test.skip / test.todo / test.onlyModifiers
{ concurrency: true }Run subtests in parallel

3. Using Test Hooks

HookRuns
beforeOnce before suite
afterOnce after suite
beforeEachBefore every test
afterEachAfter every test

4. Creating Test Assertions

APIUse
assert.equal(a, b)Strict equality
assert.deepEqual(a, b)Deep strict
assert.throws(fn, errMatch)Sync error
assert.rejects(promise, errMatch)Async error
t.assert.snapshot(...)Snapshot testing v22+

5. Testing Async Code

Example

test("fetches user", async () => {
  const user = await fetchUser(1);
  assert.equal(user.name, "Ada");
});

6. Running Tests (node --test flag)

CommandEffect
node --testDiscover and run *.test.js
node --test --watchRe-run on change
node --test --test-reporter=specSpec-style output
node --test --test-name-pattern="adds"Filter by name

7. Using Test Coverage (--experimental-coverage)

FlagNotes
--experimental-test-coverageEnables coverage report v20+
--test-coverage-include / --test-coverage-excludeFile globs
Externalc8 / nyc wrappers

8. Mocking Dependencies

Example: Built-in mock

import { test, mock } from "node:test";
test("calls api", () => {
  const fn = mock.fn(() => 42);
  assert.equal(fn(), 42);
  assert.equal(fn.mock.callCount(), 1);
});
APIUse
mock.fn(impl?)Spy / stub
mock.method(obj, "name")Replace method, auto-restore
mock.timers.enable()Fake timers
mock.module(specifier, opts)Module mocking v22.3+

9. Using Jest for Testing

FeatureDetail
Snapshot testingexpect(x).toMatchSnapshot()
Module mockingjest.mock("./db")
CoverageBuilt-in via Istanbul
ESMUse --experimental-vm-modules

10. Using Mocha and Chai

Example

import { expect } from "chai";
describe("math", () => {
  it("adds", () => expect(1 + 2).to.equal(3));
});

11. Testing HTTP Endpoints

Example: supertest

import request from "supertest";
const res = await request(app).get("/users").expect(200);
assert.equal(res.body.length, 2);

12. Integration vs Unit Testing

TypeScopeSpeed
UnitSingle function/module, mocks for depsFastest
IntegrationMultiple modules, real DB/HTTPSlower
E2EFull system, real networkSlowest
PyramidMany unit, fewer integration, fewest E2E