DEV Community

Cover image for How to Write API Integration Tests (That Actually Catch Bugs)
Taras H
Taras H

Posted on • Originally published at codenotes.tech

How to Write API Integration Tests (That Actually Catch Bugs)

API integration tests aren’t about checking 200 OK.

They exist to answer a harder question:

When a real request crosses authentication, validation, persistence, and transactions — does the system behave correctly?

Most production bugs don’t live inside a single function.

They happen between boundaries.


What Integration Tests Should Actually Prove

A useful API integration test verifies:

  • routing + request parsing
  • authentication & authorization
  • validation and error shape
  • database writes and reads
  • transaction boundaries
  • response contract
  • retry / duplicate handling
  • concurrency behavior

This sits between unit tests and end-to-end tests:

  • Unit → logic correctness
  • Integration → system behavior at boundaries
  • E2E → full user journey

Start With Risk, Not Coverage

Don’t write the same number of tests per endpoint.

Focus on endpoints that:

  • mutate important data
  • cross auth or tenant boundaries
  • involve multiple writes or transactions
  • depend on external systems
  • must handle retries or duplicates
  • have broken in production before

The goal isn’t coverage.

It’s risk-weighted confidence.


What a Good Test Looks Like

A strong integration test:

  1. sends a real HTTP request
  2. goes through real auth + validation
  3. writes to a real database
  4. asserts persisted state, not just response
const res = await request(app)
  .post('/api/orders')
  .set('Authorization', `Bearer ${token}`)
  .send(body)

expect(res.status).toBe(201)

const order = await db.order.findFirst(...)
expect(order).toBeTruthy()
Enter fullscreen mode Exit fullscreen mode

If you only check the response, you’re missing half the system.


The Critical Cases People Skip

These are where integration tests provide real value:

  • Authorization → tenant / ownership rules
  • Validation → bad input blocked before writes
  • Rollback → no partial state on failure
  • Idempotency → retries don’t duplicate effects
  • Concurrency → overlapping requests don’t break invariants

Most bugs hide here—not in the happy path.


What Not to Mock

Avoid mocking:

  • database
  • transactions
  • auth middleware
  • validation
  • your own application code

Mock only external systems like payments or email.

Mock dependencies outside your system, not inside it.


The Short Version

Good API integration tests prove:

  • real requests cross real boundaries
  • correct state is persisted
  • failures don’t leave partial data
  • retries and concurrency are safe
  • response contracts don’t break clients

They matter because production bugs usually live between components, not inside them.


👉 Full deep dive (idempotency, concurrency, rollback examples):

https://codenotes.tech/blog/how-to-write-api-integration-tests

Top comments (0)