Build a Typed REST API with Express, TypeScript & Zod

Lesson 7 of 8

Testing a Typed API with Vitest & Supertest

Everything so far has been validated by the compiler and by Zod at runtime, but neither one confirms the API actually behaves correctly end to end. That's what integration tests are for.

npm install -D vitest supertest @types/supertest

Supertest sends real HTTP requests to your Express app in-process, no separate server or port needed, and Vitest runs the assertions, both fully typed against your existing app.

Testing a validated endpoint

TypeScript

Splitting app (the Express application) from the code that calls app.listen() is what makes this possible, Supertest talks to app directly in memory, no real network socket or port conflict involved. The second test is just as important as the first: it proves the 400/Zod-validation path from the earlier lesson actually fires for bad input, not just that the happy path works.

Testing the full lifecycle

TypeScript

One test walking through create → read → delete catches a class of bug unit tests on individual functions miss entirely: whether the pieces actually agree with each other once wired together as real HTTP requests.

TIP

Test both the happy path (valid input, expected status) and at least one failure path (invalid input, missing resource) for every endpoint, a suite that only exercises success cases won't catch a broken validation rule or a wrong error status code.

📝 Testing with Vitest & Supertest Quiz

Passing score: 70%
  1. 1.Why export the Express app separately from the code that calls .listen()?

  2. 2.A good test suite for a validated endpoint should include at least one request that is expected to fail validation.

  3. 3.The library used in this lesson to send real HTTP requests to an Express app in tests is ____.