All Posts
TestingCI/CDDeveloper Tools

API Testing Strategies for Modern Engineering Teams

Kiran MayeeJune 5, 20258 min read

Shipping an API without tests is like deploying a bridge without load calculations. It might hold — or it might collapse at 2 AM on a Saturday. This guide walks through the four layers of API testing every team should implement.

Layer 1: Unit Tests

Test individual handler functions in isolation. Mock the database, external services, and file system. The goal is speed and accuracy — a failing unit test should point you to the exact line of broken logic.

// Example with Vitest
import { describe, it, expect, vi } from "vitest"
import { getUser } from "./handlers/user"

describe("getUser", () => {
  it("returns 404 when user does not exist", async () => {
    vi.mock("./db", () => ({ findUser: vi.fn().mockResolvedValue(null) }))
    const res = await getUser({ params: { id: "999" } })
    expect(res.status).toBe(404)
  })
})

Layer 2: Integration Tests

Spin up a real (or containerised) database and exercise full request ➜ handler ➜ database ➜ response flows. Use a library like supertest (Node) or httpx (Python) to send real HTTP requests to your server.

Integration tests catch issues that unit tests miss: broken SQL queries, misconfigured middleware, and transaction isolation bugs.

Layer 3: Contract Tests

A contract test ensures that the shape of your API response matches what consumers expect. Tools like Pact or simple JSON Schema assertions prevent breaking changes from reaching production.

moqapi.dev auto-generates contract tests from your route definitions — just toggle the feature in your project settings.

Layer 4: Fuzz & Chaos Testing

Feed your API unexpected inputs: oversized strings, negative numbers, emoji-heavy payloads, null bytes. Fuzz testing surfaces edge cases that manual test cases never consider.

  • Property-based testing (fast-check, Hypothesis) generates thousands of random inputs.
  • Chaos engineering injects failures into dependencies to test resilience.

CI/CD Integration

Tests without automation are tests that don't run. Add all four layers to your CI pipeline:

  1. Pre-merge: Unit + contract tests (fast, blocking).
  2. Post-merge: Integration tests against a staging database.
  3. Nightly: Fuzz testing with extended timeouts.

moqapi.dev's webhook system can trigger your CI pipeline on every deploy, ensuring mock endpoints and production endpoints stay in sync.

Recommended Test Ratios

A healthy API test suite follows the testing pyramid:

  • ~60% unit tests — fast, cheap, abundant.
  • ~25% integration tests — slower, more realistic.
  • ~10% contract tests — schema-focused, catches drift.
  • ~5% fuzz/chaos — exploratory, catches the unknown.

Final Thoughts

The best time to write API tests was at the start of the project. The second-best time is now. Start with the layer that gives you the most coverage for the least effort — usually unit tests — and work your way outward.

Share this article:

About the Author

Kiran Mayee

Founder and sole developer of moqapi.dev. Full-stack engineer with deep experience in API platforms, serverless runtimes, and developer tooling. Built moqapi to solve the mock data and deployment friction she experienced firsthand building production APIs.

Ready to build?

Start deploying serverless functions in under a minute.

Get Started Free