Testing Strategy
Critical rules
- Pyramid: many fast unit tests → fewer integration → thin load/chaos top.
- Unit tests mock deps with
mock<DepsType>()/mockDeep— nevervi.mockfor app modules. - Integration tests use real localhost DB only; guardrails must throw on non-localhost URLs.
- Name by type:
*.test.ts(unit),*.test.int.ts(integration),load/*.js,chaos/*. - Hard to test = design smell (
fn-args-depsmocks only what the function uses). - Faker for realistic unique fixtures so tests parallelize without cleanup.
- Before long setup/Prisma/Faker examples, read the matching resource below.
Workflow
- Pick the layer by the question:
- Logic / injectable deps? → Unit (mock deps, ms)
- Crosses real boundary (DB, FS)? → Integration (
.test.int.ts, localhost) - Concurrent traffic / SLOs? → Load (
performance-testing) - Survive dependency failure? → Chaos (
performance-testing)
- Unit: typed mocks from the deps interface; assert Results and values (
writing-tests). - Integration: real DB, seed unique Faker data, query only that data.
- Ensure
vitest.setup.tsenforces localhost DB +vi.clearAllMocks()between tests. - Prisma fluent API:
mockDeep<PrismaClient>()(+$transactioncallback helper). - Load/chaos: critical paths only — see
performance-testing.
Resources
- references/examples.md — unit/integration/Prisma/Faker patterns. Read when implementing a layer.
- references/setup.md — file naming, guardrails, vitest config, load smoke sketch. Read when scaffolding the suite.
- references/rationalizations.md — excuse→reality and red flags. Read when tempted to skip the pyramid.
Validation
- Each test at the right pyramid layer
- Unit:
mock<DepsType>(), no app-modulevi.mock - Integration:
.test.int.ts+ localhost-only guardrail - Prisma via
mockDeep; Faker unique IDs/emails for parallel runs - Setup clears mocks between tests
Constraints
- Not the red-green-refactor loop (
tdd-workflow) or assertion craft (writing-tests). - Deep k6 profiles and Toxiproxy live in
performance-testing. - Adjacent:
fn-args-deps,result-types.