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
| API | Use |
|---|---|
describe(name, fn) | Group tests |
test(name, fn) / it(...) | Individual test |
test.skip / test.todo / test.only | Modifiers |
{ concurrency: true } | Run subtests in parallel |
3. Using Test Hooks
| Hook | Runs |
|---|---|
before | Once before suite |
after | Once after suite |
beforeEach | Before every test |
afterEach | After every test |
4. Creating Test Assertions
| API | Use |
|---|---|
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)
| Command | Effect |
|---|---|
node --test | Discover and run *.test.js |
node --test --watch | Re-run on change |
node --test --test-reporter=spec | Spec-style output |
node --test --test-name-pattern="adds" | Filter by name |
7. Using Test Coverage (--experimental-coverage)
| Flag | Notes |
|---|---|
--experimental-test-coverage | Enables coverage report v20+ |
--test-coverage-include / --test-coverage-exclude | File globs |
| External | c8 / 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);
});
| API | Use |
|---|---|
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
| Feature | Detail |
|---|---|
| Snapshot testing | expect(x).toMatchSnapshot() |
| Module mocking | jest.mock("./db") |
| Coverage | Built-in via Istanbul |
| ESM | Use --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
| Type | Scope | Speed |
|---|---|---|
| Unit | Single function/module, mocks for deps | Fastest |
| Integration | Multiple modules, real DB/HTTP | Slower |
| E2E | Full system, real network | Slowest |
| Pyramid | Many unit, fewer integration, fewest E2E | — |