Backend Integration Testing
Purpose
Prove the assembled backend works: routes through middleware, validation, authorization, services, and a real database — exercised over HTTP the way clients will call it. This is where authorization and validation guarantees get verified, not just designed.
When to Use
- For endpoint behavior, auth/authz enforcement, DB-touching flows, webhook intake, job execution.
- Not for pure logic (
backend-unit-testing) or full multi-app E2E (client packs / ../../testing-strategy).
Inputs
- Endpoint design + auth matrix (
rest-api-design, backend-authorization).
- Schema/migrations (
../../database/database-migrations), seed strategy (../../database/seed-data).
Discovery Questions
- How does a test get a real database — containerized per suite (testcontainers-style), shared with per-test isolation, or transaction-rollback per test?
- How do tests authenticate (helper that mints sessions/tokens per persona: anonymous, user A, user B, admin, other-tenant)?
- Which flows are release-critical and must be covered first?
Responsibilities
- Stand up the app + real database in tests: migrations applied, known seed state, isolation between tests (truncate/transaction/unique-tenant per test) — SQLite-in-place-of-Postgres “convenience” swaps test a different database; don't.
- Fake only true externals: provider clients stubbed at your interface (
third-party-integrations); queues either run inline/test-mode or assert enqueue + test workers directly (background-jobs).
- Cover per endpoint: success shape (contract match —
api-contracts), validation rejection (malformed/unknown-field/oversize), and the authorization negative suite:
- anonymous → 401 on protected routes;
- User A cannot read/update/delete User B's resource;
- non-admin → admin action rejected;
- client-supplied ownership/tenant IDs ignored (scope stays the session's);
- cross-tenant access rejected with a valid guessed ID.
- Cover auth flows end-to-end: signup/login/refresh/logout, expired/tampered tokens, reset-token single-use (
backend-authentication).
- Cover non-HTTP entries: inbound webhooks (bad signature rejected, duplicate deduped —
webhooks), job handlers (idempotent re-run — background-jobs).
- Keep the suite honest in CI: hermetic (no shared external state), parallelizable, failures reproducible locally.
Required Workflow
- Choose the DB provisioning + isolation strategy.
- Build test helpers: app bootstrap, persona auth, seed factories.
- Cover release-critical flows first; per endpoint add success + validation + authz-negative cases.
- Add webhook/job-path tests.
- Wire into CI as the merge gate; keep runtime bounded (parallel, scoped seeds).
Decision Rules
- Same database engine as production, always.
- The authorization negative suite is mandatory per scoped resource — a missing cross-user test is a missing control.
- Assert response contracts (status + shape), not implementation artifacts.
- Flaky integration tests get fixed or quarantined same-day; a red-noise suite gates nothing.
Rules
- No test hits real third-party services or sends real email (
third-party-integrations sinks).
- Tests own their data; no dependence on execution order or leftover state.
- Every bug fix at this layer lands with its regression test.
Anti-Patterns
- Mocking the data layer in an "integration" test — that's a slow unit test.
- Testing only happy paths; skipping the negative authz suite.
- One shared mutable seed database for the whole suite.
- Asserting exact error strings instead of codes/shapes.
- A 40-minute suite nobody runs locally.
Validation Checklist
Definition of Done
An integration suite running real HTTP against the app with a production-engine database — covering critical flows, validation rejection, and the full authorization negative suite — hermetic, CI-gating, and reproducible locally.
Related Skills
backend-unit-testing, ../../testing-strategy, backend-authorization, ownership-authorization, backend-authentication, backend-validation, webhooks, background-jobs, ../../database/database-migrations, ../../database/seed-data.
Related Knowledge
../../../knowledge/ (critical flows, personas/tenancy model).
Related References
../../../references/backend/testing/ (helper patterns, when populated).
Context Loading Guidance
- Requires: endpoint + authz matrix, schema/seed strategy, CI constraints.
- Does not require: service internals (tests go over HTTP), provider docs.
- May load:
backend-authorization (negative matrix), ../../database/seed-data.
- Stop when: the suite plan (or tests) covering the matrix is done and CI-wired.
Token Efficiency Guidance
Drive coverage from the endpoint × authz matrix — each cell is a test case; don't re-derive cases per endpoint in prose.
1---2name: backend-integration-testing3description: Use to plan backend integration tests — real HTTP requests against the app with a real (containerized) database, covering auth flows, authorization negative tests (cross-user/cross-tenant/role), validation rejection, and webhook/job paths. External providers stay faked.4---56# Backend Integration Testing78## Purpose910Prove the assembled backend works: routes through middleware, validation, authorization, services, and a **real database** — exercised over HTTP the way clients will call it. This is where authorization and validation guarantees get *verified*, not just designed.1112## When to Use1314- For endpoint behavior, auth/authz enforcement, DB-touching flows, webhook intake, job execution.15- **Not** for pure logic (`backend-unit-testing`) or full multi-app E2E (client packs / `../../testing-strategy`).1617## Inputs1819- Endpoint design + auth matrix (`rest-api-design`, `backend-authorization`).20- Schema/migrations (`../../database/database-migrations`), seed strategy (`../../database/seed-data`).2122## Discovery Questions2324- How does a test get a real database — containerized per suite (testcontainers-style), shared with per-test isolation, or transaction-rollback per test?25- How do tests authenticate (helper that mints sessions/tokens per persona: anonymous, user A, user B, admin, other-tenant)?26- Which flows are release-critical and must be covered first?2728## Responsibilities2930- Stand up the **app + real database** in tests: migrations applied, known seed state, isolation between tests (truncate/transaction/unique-tenant per test) — SQLite-in-place-of-Postgres “convenience” swaps test a different database; don't.31- Fake only true externals: provider clients stubbed at your interface (`third-party-integrations`); queues either run inline/test-mode or assert enqueue + test workers directly (`background-jobs`).32- Cover per endpoint: success shape (contract match — `api-contracts`), validation rejection (malformed/unknown-field/oversize), and the **authorization negative suite**:33 - anonymous → 401 on protected routes;34 - **User A cannot read/update/delete User B's resource**;35 - **non-admin → admin action rejected**;36 - **client-supplied ownership/tenant IDs ignored** (scope stays the session's);37 - **cross-tenant access rejected** with a valid guessed ID.38- Cover auth flows end-to-end: signup/login/refresh/logout, expired/tampered tokens, reset-token single-use (`backend-authentication`).39- Cover non-HTTP entries: inbound webhooks (bad signature rejected, duplicate deduped — `webhooks`), job handlers (idempotent re-run — `background-jobs`).40- Keep the suite honest in CI: hermetic (no shared external state), parallelizable, failures reproducible locally.4142## Required Workflow43441. Choose the DB provisioning + isolation strategy.452. Build test helpers: app bootstrap, persona auth, seed factories.463. Cover release-critical flows first; per endpoint add success + validation + authz-negative cases.474. Add webhook/job-path tests.485. Wire into CI as the merge gate; keep runtime bounded (parallel, scoped seeds).4950## Decision Rules5152- Same database engine as production, always.53- The authorization negative suite is **mandatory per scoped resource** — a missing cross-user test is a missing control.54- Assert response contracts (status + shape), not implementation artifacts.55- Flaky integration tests get fixed or quarantined same-day; a red-noise suite gates nothing.5657## Rules5859- No test hits real third-party services or sends real email (`third-party-integrations` sinks).60- Tests own their data; no dependence on execution order or leftover state.61- Every bug fix at this layer lands with its regression test.6263## Anti-Patterns6465- Mocking the data layer in an "integration" test — that's a slow unit test.66- Testing only happy paths; skipping the negative authz suite.67- One shared mutable seed database for the whole suite.68- Asserting exact error strings instead of codes/shapes.69- A 40-minute suite nobody runs locally.7071## Validation Checklist7273- [ ] Real same-engine DB, migrations + isolation strategy.74- [ ] Persona auth helpers (anonymous, A, B, admin, other-tenant).75- [ ] Per endpoint: success, validation rejection, authz negatives.76- [ ] Cross-user / non-admin / untrusted-ID / cross-tenant tests present.77- [ ] Webhook + job paths covered; externals faked.78- [ ] Suite hermetic, parallel, gating merges.7980## Definition of Done8182An integration suite running real HTTP against the app with a production-engine database — covering critical flows, validation rejection, and the full authorization negative suite — hermetic, CI-gating, and reproducible locally.8384## Related Skills8586`backend-unit-testing`, `../../testing-strategy`, `backend-authorization`, `ownership-authorization`, `backend-authentication`, `backend-validation`, `webhooks`, `background-jobs`, `../../database/database-migrations`, `../../database/seed-data`.8788## Related Knowledge8990`../../../knowledge/` (critical flows, personas/tenancy model).9192## Related References9394`../../../references/backend/testing/` (helper patterns, when populated).9596## Context Loading Guidance9798- **Requires:** endpoint + authz matrix, schema/seed strategy, CI constraints.99- **Does not require:** service internals (tests go over HTTP), provider docs.100- **May load:** `backend-authorization` (negative matrix), `../../database/seed-data`.101- **Stop when:** the suite plan (or tests) covering the matrix is done and CI-wired.102103## Token Efficiency Guidance104105Drive coverage from the endpoint × authz matrix — each cell is a test case; don't re-derive cases per endpoint in prose.