fix(test): isolate pay tests from eager env.ts to remove parallel-load race#119
fix(test): isolate pay tests from eager env.ts to remove parallel-load race#119AquiGorka wants to merge 2 commits into
Conversation
…d race The pay unit tests mock their infra deps (config.ts→PGlite, logger, jwt, channel-service, channel-resolver) but the real src/config/env.ts still leaked into the graph via the auth-middleware chain (service-auth-secret.ts imports MODE + SERVICE_AUTH_SECRET from env.ts). env.ts evaluates every requireEnv at module load — a deliberate production fail-fast (the service refuses to start half-configured), kept as-is. But in the pay tests that eager read has no real env, so under `deno test --parallel` on a cold CI cache it became a load-order race surfacing as "DATABASE_URL is not loaded" in the DB-touching pay tests (34 passed / 11 failed, intermittently). Complete the existing isolation: mock service-auth-secret.ts in the pay test import map (same mechanism as the other mocks). env.ts is no longer in any pay test's module graph (verified via `deno info`), so the eager reads never run and the race is gone. Production env.ts + service-auth-secret.ts are untouched.
|
Closing — superseded by #120 (pin deno to 2.8.2). The CI The existing mocks already isolate the pay tests correctly on 2.8.2, so the extra |
Summary
Fixes the flaky
testCI job (the pay unit tests intermittently failing34 passed / 11 failedwithError: DATABASE_URL is not loaded). The failure is a parallel-module-load race, not a logic bug, and it is independent of any feature PR — re-running known-green code (feat/pg-notify-event-bus) in the current CI environment reproduces it identically.Root cause
The pay tests are unit tests that mock their infra deps in
src/http/v1/pay/tests/deno.json(config.ts→PGlite, logger, jwt, channel-service, channel-resolver). But the realsrc/config/env.tsstill leaked into their module graph via the auth-middleware chain:env.tsevaluates everyrequireEnvat module load:That eager read is a deliberate production fail-fast — the service must refuse to start half-configured — and is kept as-is. But in the pay tests there is no real env, so under
deno test --parallelon a cold CI cache the eager evaluation became a load-order race (the first missing var,DATABASE_URL, throws; which tests it takes down is timing-dependent → intermittent11 failed).Fix
Complete the existing test isolation: mock
service-auth-secret.tsin the pay test import map (same mechanism as the other mocks), so the pay tests never evaluate the realenv.ts.The mock mirrors the real module's exports + crypto-key shape with a fixed test secret. Production
env.tsandservice-auth-secret.tsare untouched (fail-fast preserved); not lazified.Verification
deno infoconfirmsenv.tsis no longer in any of the 11 previously-failing pay tests' module graphs (env.ts = 0across all).env -u DATABASE_URL DENO_DIR=$(mktemp -d) deno test --parallel --config src/http/v1/pay/tests/deno.json→116 passed | 0 failed, repeated).deno fmt --check+deno lintgreen.