Skip to main content
MediumTooling & TestingTest

Write Tests for an API Client

You're writing tests for an `ApiClient` class — a reusable wrapper around `fetch` that handles errors, parses JSON, and retries transient server failures. The class is in `src/ApiClient.ts` — read-only. Your job is in `...

What you will practice

TypeScriptAsync PatternsTestingVitestAPI Client

Requirements

  • Use Vitest (`describe`, `it`, `expect`, `vi`) — already available in the runtime.
  • Import `ApiClient` from `'../src/ApiClient'`.
  • Mock `globalThis.fetch` using `vi.fn().mockResolvedValue(...)` — do not make real network calls.
  • Every test must pass against the reference implementation.
  • Your suite must produce at least one failing test against each of four buggy variants: missing error handling on any non-ok response, 4xx treated as success (only 5xx throws), raw Response object returned instead of parsed JSON, and 401 triggering retries when it should throw immediately.

Starter files

src/ApiClient.tsReference starter
tests/ApiClient.test.tsEditable tests

What the judge checks

  • Runs in the node environment with the node-vitest runner.
  • Uses a 15000ms judge budget.
  • Behavior rules include: Tests Pass On Reference, Tests Catch Missing Error Handling, Tests Catch Wrong Status Check, Tests Catch No Json Parse.

Constraints

  • Do not modify `src/ApiClient.ts`.
  • All assertions go in `tests/ApiClient.test.ts`.
  • Use `vi.fn()` for fetch mocking — no real HTTP calls.

Example behavior

Input
GET /users → 200 with body { id: 1 }
Output
Promise resolves to { id: 1 }

A 200 response is parsed as JSON and returned directly.

Input
GET /not-found → 404
Output
Promise rejects with Error('HTTP 404')

Any non-ok status that isn't retried must throw with the status code.

Follow-up

The retry strategy here is a flat counter. Real systems use exponential backoff — each retry waits 2× longer than the last. How would you test that without making your test suite take seconds to run?