hectoday
DocsCoursesChangelog GitHub
DocsCoursesChangelog GitHub

Access Required

Enter your access code to view courses.

Invalid code

← All courses Testing APIs with @hectoday/http

Why Test

  • What Testing Gives You
  • Types of Tests
  • Project Setup

Unit Testing

  • Testing Pure Functions
  • Testing Zod Schemas
  • Testing Business Logic

Integration Testing

  • Testing Route Handlers
  • Testing GET Endpoints
  • Testing POST Endpoints
  • Testing Error Responses
  • Testing Authentication

Test Helpers

  • Factories and Fixtures
  • Test Database Isolation
  • Request Helpers

Advanced Testing

  • Mocking External Services
  • Testing Background Jobs
  • Testing Edge Cases

Putting It All Together

  • Test Organization
  • Checklist and Capstone

Types of Tests

Three levels

Tests operate at different levels of abstraction:

Unit tests test one function in isolation. No database, no HTTP, no external services. Fast — hundreds per second.

test("formatBookV2 formats ratings correctly", () => {
  const result = formatBookV2(bookRow);
  expect(result.ratings.average).toBe(4.5);
});

Integration tests test multiple components working together. A route handler that queries the database, validates input, and returns a response.

test("GET /v2/books returns books with authors", async () => {
  const response = await app.fetch(new Request("http://localhost/v2/books"));
  const data = await response.json();
  expect(response.status).toBe(200);
  expect(data[0].author.name).toBeDefined();
});

End-to-end (E2E) tests test the entire system — a running server, real HTTP requests, real database. The slowest but most realistic.

test("full order flow", async () => {
  const loginRes = await fetch("http://localhost:3000/login", { method: "POST", body: loginData });
  const token = (await loginRes.json()).token;
  const orderRes = await fetch("http://localhost:3000/orders", {
    method: "POST",
    headers: { Authorization: `Bearer ${token}` },
    body: orderData,
  });
  expect(orderRes.status).toBe(201);
});

The testing pyramid

        /  E2E  \          Few — slow, expensive, realistic
       /  Integ  \         Some — moderate speed, test component interaction
      /   Unit    \        Many — fast, cheap, test individual functions

Many unit tests: Fast, cheap, test individual pieces. Catch most bugs.

Some integration tests: Test that pieces work together. Catch wiring bugs.

Few E2E tests: Test critical user flows. Catch system-level bugs.

This course focuses on unit and integration tests — the two levels that give the most value for API development. E2E tests for APIs are essentially integration tests that use a running server, which is rarely necessary with Hectoday HTTP’s app.fetch().

Which level for what

What to testLevelWhy
Transformers (formatBookV2)UnitPure function, no dependencies
Zod schemasUnitSchema in, result out
Database queriesIntegrationNeeds a database
Route handlersIntegrationNeeds routing + database
Auth flowsIntegrationNeeds multiple routes + state
Background jobsUnit + IntegrationHandler logic (unit), enqueue behavior (integration)

Exercises

Exercise 1: Classify these as unit, integration, or E2E: testing a password hash function, testing a login endpoint, testing a full checkout flow.

Exercise 2: Write a unit test for a pure function (e.g., a helper that formats a date). No database, no HTTP.

Exercise 3: Describe one test at each level for the book catalog API.

Why should you write more unit tests than integration tests?

← What Testing Gives You Project Setup →

© 2026 hectoday. All rights reserved.