Skip to content

Testing APIs

Tests are what let you change an API with confidence. Three layers, each catching a different class of bug, give good coverage without redundant effort.

flowchart TD
  U[Unit: handlers, validation, pure logic - many, fast] --> I[Integration: real routes end-to-end - fewer]
  I --> C[Contract: responses match the OpenAPI spec - focused]
Many fast unit tests, fewer integration tests, focused contract checks
  • Unit tests — exercise pure pieces: a validator, a pagination helper, an error mapper. Fast and numerous.
  • Integration tests — send real requests through the actual router and assert status, headers, and body. These catch wiring bugs unit tests miss.
  • Contract tests — assert that responses conform to the OpenAPI schema, so the implementation and the published contract never drift.

Frameworks like Hono expose app.request(...), so you can call routes in-process without a network:

JavaScript

For each endpoint, test the happy path and the failure paths: the right status code, the response shape, the error body for invalid input (does it match your problem+json?), auth required where expected, and pagination metadata on collections.

Which test layer sends real requests through the actual router?
What do contract tests specifically guard against?
Why explicitly test failure paths?