Integration Tests
integration owns only true inter-service black-box tests.
Each suite must raise real service processes, speak only over public HTTP/gRPC/Redis contracts, and avoid imports from internal/... packages of tested services.
Layout
integration/
├── README.md
├── authsessionmail/
│ ├── authsession_mail_test.go
│ └── harness_test.go
├── gatewayauthsessionmail/
│ ├── gateway_authsession_mail_test.go
│ └── harness_test.go
├── gatewayauthsessionusermail/
│ └── gateway_authsession_user_mail_test.go
├── authsessionuser/
│ ├── authsession_user_test.go
│ └── harness_test.go
├── gatewayauthsession/
│ ├── harness_test.go
│ └── gateway_authsession_test.go
├── gatewayauthsessionuser/
│ ├── gateway_authsession_user_test.go
│ └── harness_test.go
├── gatewayuser/
│ ├── gateway_user_test.go
│ └── harness_test.go
├── notificationgateway/
│ └── notification_gateway_test.go
├── notificationmail/
│ └── notification_mail_test.go
├── notificationuser/
│ └── notification_user_test.go
├── go.mod
├── go.sum
└── internal/
├── contracts/
│ ├── gatewayv1/
│ │ └── contract.go
│ └── userv1/
│ └── contract.go
└── harness/
├── binary.go
├── keys.go
├── mail_stub.go
├── process.go
├── redis_container.go
├── smtp_capture.go
└── user_stub.go
Rules
- Keep suites black-box. Do not import
galaxy/gateway/internal/...,galaxy/authsession/internal/..., or any other service-owned internal package. - Start real binaries from
cmd/...and talk to them only through their published HTTP, gRPC, and Redis contracts. - Put boundary-specific orchestration and assertions into the owning suite package, not into shared helpers.
- Put only generic process/runtime utilities into
internal/harness. - Put only public-contract helpers into
internal/contracts/....
Current Boundary Suites
gatewayauthsessionverifies the integration boundary between realEdge Gatewayand realAuth / Session Service.authsessionuserverifies the integration boundary between realAuth / Session Serviceand realUser Service.authsessionmailverifies the integration boundary between realAuth / Session Serviceand realMail Service.gatewayauthsessionmailverifies the public auth flow across realEdge Gateway, realAuth / Session Service, and realMail Service.gatewayuserverifies the direct authenticated self-service boundary between realEdge Gatewayand realUser Service.gatewayauthsessionuserverifies the full public-auth plus authenticated-account chain across realEdge Gateway, realAuth / Session Service, and realUser Service.notificationgatewayverifies that realNotification Servicepush publication is consumed and fanned out by realEdge Gatewayfor all user-facing push types.notificationmailverifies that realNotification Servicetemplate-mode mail publication is consumed by realMail Servicefor all notification email types.notificationuserverifies that realNotification Serviceenriches recipients through realUser Serviceand preserves Redis stream progress semantics for missing or temporarily unavailable users.gatewayauthsessionusermailverifies the full public registration chain across realEdge Gateway, realAuth / Session Service, realUser Service, and realMail Service, including the regression that auth-code mail bypassesnotification:intents.
The current fast suites still use one isolated miniredis instance plus either
real downstream processes or external stateful HTTP stubs where appropriate.
authsessionmail, gatewayauthsessionmail, notificationgateway,
notificationmail, notificationuser, and gatewayauthsessionusermail are
the deliberate exceptions: they use one real Redis container through
testcontainers-go, because those boundaries must exercise real Redis stream,
persistence, or scheduling behavior.
authsessionmail additionally contains one targeted SMTP-capture scenario for
the real smtp provider path, while gatewayauthsessionmail keeps Mail Service in stub mode and extracts the confirmation code through the trusted
operator delivery surface.
Running
Run from the module directory:
cd integration
go test ./gatewayauthsession/...
go test ./authsessionuser/...
go test ./authsessionmail/...
go test ./gatewayauthsessionmail/...
go test ./gatewayuser/...
go test ./gatewayauthsessionuser/...
go test ./notificationgateway/...
go test ./notificationmail/...
go test ./notificationuser/...
go test ./gatewayauthsessionusermail/...
Useful regression commands after boundary changes:
go test ./gatewayauthsession/...
go test ./authsessionuser/...
go test ./authsessionmail/...
go test ./gatewayauthsessionmail/...
go test ./gatewayuser/...
go test ./gatewayauthsessionuser/...
go test ./notificationgateway/...
go test ./notificationmail/...
go test ./notificationuser/...
go test ./gatewayauthsessionusermail/...
cd ../gateway && go test ./...
cd ../authsession && go test ./... -run GatewayCompatibility
cd ../user && go test ./...
Do not use go test ./... from the repository root. The repository is organized through go.work, so verification should stay module-scoped.
Adding A New Boundary Suite
- Create
integration/<boundary>/for the new inter-service boundary. - Keep suite-local fixtures, scenario helpers, and assertion helpers inside that package.
- Reuse
internal/harnessonly for generic concerns such as binary build/run, ports, keys, Redis, and shared external stubs. - Add new helpers to
internal/contracts/<contract>/only when they describe a reusable public wire contract. - Prefer fast deterministic infrastructure by default: in-memory test doubles,
httpteststubs, andminiredis.
Real Redis Suites
Fast suites stay on miniredis by default.
When one boundary explicitly needs real Redis semantics, prefer a package-local
container setup through testcontainers-go plus reusable helpers in
internal/harness, as done by authsessionmail and
gatewayauthsessionmail.
Current rule of thumb:
- use
minirediswhen the boundary does not depend on Redis persistence or scheduling behavior - use
testcontainers-goonly when the real Redis process materially changes the behavior being verified