Skip to content

test: add Testcontainers integration tests for every service - #7

Merged
devinder-dev merged 1 commit into
mainfrom
phase-5-testcontainers
Jun 21, 2026
Merged

devinder-dev merged 1 commit into
mainfrom
phase-5-testcontainers

Conversation

@devinder-dev

Copy link
Copy Markdown
Owner

Summary

  • Real Postgres + RabbitMQ + Redis in tests via Testcontainers, no mocks for any infra - the actual graded testing-pyramid requirement
  • One integration test file per service: order, kitchen, notification, menu
  • order's buildServer() extracted into its own server.ts so tests can server.inject() against it without triggering the real startup chain; kitchen/notification's tests dynamically import the whole index.ts to exercise the real consumer wiring end to end

Bugs found and fixed by these tests

  • @testcontainers/postgresql's default wait strategy requires a Docker HEALTHCHECK the plain postgres:16 image doesn't have - hung forever. Fixed with an explicit log-message wait strategy.
  • connect() in mq.ts never listened for RecoveringChannelModel's own "error" event (separate from "disconnect") - an unhandled EventEmitter error crashes the whole process. This is a real production hardening fix, not just a test fix.
  • notification's first test asserted exact event-arrival order, which is flaky under concurrent handler completions when events are published back-to-back with no delay. Fixed to assert presence regardless of order.

Test plan

  • bun run typecheck green across all services
  • Snyk code scan on all 5 changed packages - 0 issues
  • bun test from repo root: 12 pass, 0 fail, confirmed stable across repeated runs, exit code 0
  • No orphaned Testcontainers left running after the suite (Ryuk reaper confirmed clean)

Real Postgres + RabbitMQ + Redis in tests, no mocks for any infra.
Each service's db.ts reads connection env vars at module-load time,
so each test sets them in beforeAll then dynamically imports the
module under test.

order's buildServer() is extracted into its own server.ts so tests
can server.inject() against it without triggering index.ts's real
startup chain; kitchen/notification's tests dynamically import the
whole index.ts (ephemeral PORT=0) since they intentionally exercise
the real consumer wiring.

Also fixes two real bugs these tests surfaced:
- connect() in mq.ts never listened for RecoveringChannelModel's own
  "error" event, separate from "disconnect" - an unhandled EventEmitter
  error crashes the process, so a service could have crashed on
  certain connection failures even outside of tests
- notification's event-order assertion was flaky since concurrent
  handler completions can race when events arrive with no delay
  between them, unlike the real ~3s gap between accepted and ready
@devinder-dev
devinder-dev merged commit cf90b9f into main Jun 21, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant