Skip to main content

Approach selection

Scope: pick the cheapest verification that actually proves your claim. This page is the decision table; the scripts live in procedures, the things you test against in infrastructure.

What you're testingApproachClerk network call?
Unit test — guard logic, pipes, decoratorsMock verifyToken() + synthetic request.authNone
Unit test — webhook sync serviceMock PrismaService + ClerkBackendServiceNone
Backend e2e — portal endpointsGuard-override pattern (override the guards in test/*.e2e-spec.ts)None
Backend e2e — webhook endpointPre-signed svix payload with a known secretNone
Frontend unit — components using useAuthMock the @clerk/react moduleNone
Service method against real DB, no HTTPContext probe (Recipe D)None
Webhook handler mirrors an eventSigned-payload replay (Recipe C)None
Real Clerk event → webhook → DB (live)Relay round-trip (Recipe A)Yes
Portal endpoint works for a real userReal org-active token (Recipe B)None (if DB pre-mirrored)
Full signup → gate → HTTP responseRecipe E (A+B combined)Yes

Selection rules:

  • Default to the cheapest row that proves your claim. A bare 401 only proves the route exists.
  • Mocked unit tests don't prove the server boots or the DB accepts the query — pair them with the runtime-verification mandate before calling a task done.
  • For anything depending on auth, org resolution, or quotas, use a real token (Recipe B) or the combined flow (Recipe E), and assert the real response body plus the DB side effects — not just the status code.

Source-checked against optolink-backend @ 29f8589 and optolink-portal @ 7d31d45, 2026-10-06 (mock patterns: clerk-auth.guard.spec.ts, clerk-sync.service.spec.ts, test/portal-*.e2e-spec.ts, src/**/*.test.tsx). Recipe scripts themselves are verified on their own procedure pages.