Lab 13: Testing

Objective

Write type-safe tests using Node.js built-in test runner, create typed mocks, use assertion helpers, and test generic/async code confidently.

Time

30 minutes

Prerequisites

  • Lab 02 (Functions), Lab 04 (Classes), Lab 09 (Async)

Tools

  • Docker image: zchencow/innozverse-ts:latest (Node 20 built-in test runner)


Lab Instructions

Step 1: Node.js Built-in Test Runner

import { test, describe, it, before, after, beforeEach, afterEach } from "node:test";
import assert from "node:assert/strict";

// Simple test
test("add numbers", () => {
    assert.equal(2 + 2, 4);
    assert.equal(10 - 3, 7);
});

// Describe block
describe("Math utilities", () => {
    function clamp(n: number, min: number, max: number): number {
        return Math.min(Math.max(n, min), max);
    }

    it("clamps above max", () => assert.equal(clamp(100, 0, 10), 10));
    it("clamps below min", () => assert.equal(clamp(-5, 0, 10), 0));
    it("keeps value in range", () => assert.equal(clamp(5, 0, 10), 5));
});

// Async test
test("async operation", async () => {
    const result = await Promise.resolve(42);
    assert.equal(result, 42);
});

// Test with error assertion
test("throws on invalid input", () => {
    function parsePositive(n: number): number {
        if (n <= 0) throw new RangeError("Must be positive");
        return n;
    }
    assert.throws(() => parsePositive(-1), RangeError);
    assert.equal(parsePositive(5), 5);
});

💡 Node.js 18+ has a built-in test runner (node:test) — no Jest or Mocha needed for simple test suites. It supports describe/it/test, async tests, subtests, mocking, and --test CLI flag. For TypeScript, run with ts-node --test or compile first.

📸 Verified Output:


Step 2: Type-Safe Assertions & Custom Matchers

💡 asserts val is T return type makes custom assertion functions narrow types. After assertDefined(user), TypeScript removes null | undefined from user's type. Without this return type, TypeScript doesn't know the assertion changed the type — you'd still need ! or ?. afterward.

📸 Verified Output:


Steps 3–8: Mocks, Stubs, Spies, Test Utilities, Integration Tests, Capstone

📸 Verified Output:


Summary

TypeScript testing is expressive and type-safe. You've written typed assertions with asserts type predicates, created mock factories, implemented spy functions, built test data with builders, done property-based testing, and ran a complete OrderService test suite — all with zero external testing frameworks.

Further Reading

Last updated