Infrastructure Testing
Setup and patterns for repository/infrastructure integration tests with Drizzle + Effect + Vitest
Infrastructure Testing Overview
What we test
- CRUD:
add,fetchByUserId,update,remove - Queries:
existsByUserId,fetchByPhoneNumber,fetchWithCompleteProfiles(pagination) - Edge cases: non-existent
userId, uniqueuserIdconstraint, cascade delete - Serialization: nested VOs flattened to columns (address, social links)
Before each test, we boot a disposable database, instantiate the repository, and wipe tables so every run starts from zero. After each test, we clean up the database resources. In short: beforeEach(async () => { ... }) brings up a clean state, and afterEach(async () => { ... }) tears it down.
Verifies add(...) persists and fetchByUserId(...) returns Option.Some with the same entity.
Uses update(...) to change persisted fields and re-fetches to assert the mutations are saved.
Exercises fetchByPhoneNumber(...): expects a non-empty list containing the created host.
Calls remove(id) and verifies fetchByUserId(...) returns Option.None afterward.
Validates existsByUserId(...) toggles from false to true after inserting a host.
Ensures fetchWithCompleteProfiles(...) returns only hosts with complete profile fields (dob, phoneNumber, profileImage).
Checks fetchByUserId(...) for a non-existent UUID returns Option.None.
Running the tests
- Run:
pnpm vitest(or your workspace script)
Key Lessons
- Fresh DB per test: Use
setupTestDatabase()andcleanupDatabase()for isolation - Test all CRUD: Cover
add,fetch,update,removeoperations - Effect patterns: Use
E.runPromisefor assertions,E.runSyncfor factories - Option handling: Verify
O.isSomeandO.isNonefor repository results - Edge cases: Test non-existent data scenarios