| name | test-database-feature |
| description | Run tests with local database setup and repository pattern |
Test Database Feature
This skill guides you through testing features that interact with the database using repository integration tests.
When to Use
- After implementing new repository methods
- After modifying database schema
- Testing use cases that depend on database
- Verifying data access patterns
Prerequisites
1. Start Local Database
# From project root
docker-compose -f assets/local/docker-compose.yml up -d
Database Configuration:
- Host:
localhost - Port:
3306 - Database:
rapid_db - User:
rapid_user - Password:
rapid_password
Verify Database is Running:
docker ps | grep mysql
2. Setup Prisma
cd backend
# Generate Prisma client
npm run prisma:generate
# Run migrations
npm run prisma:migrate
# Seed initial data (optional)
npm run db:seed
Repository Integration Test Pattern
Repository tests MUST connect to actual database (not mocks).
Example: Checklist Repository Test
Based on backend/src/api/features/checklist-management/__tests__/repository-integration.test.ts:
import { describe, it, expect, beforeEach } from 'vitest';
import { PrismaClient } from '@prisma/client';
import { makePrismaCheckRepository } from '../domain/repository';
// Use actual database connection
const prisma = new PrismaClient();
describe('CheckRepository Integration Tests', () => {
// Clean up before each test
beforeEach(async () => {
await prisma.checkListSet.deleteMany();
});
it('should store and retrieve checklist set', async () => {
const repo = makePrismaCheckRepository(prisma);
// Create test data
const checkListSet = {
id: 'test-id-1',
name: 'Test Checklist',
description: 'Test Description',
documents: [
{
id: 'doc-1',
name: 'Document 1',
s3Key: 'test/doc1.pdf'
}
]
};
// Store
await repo.storeCheckListSet({ checkListSet });
// Retrieve
const sets = await repo.findAllCheckListSets();
// Verify
expect(sets).toHaveLength(1);
expect(sets[0].name).toBe('Test Checklist');
});
it('should find checklist set by id', async () => {
const repo = makePrismaCheckRepository(prisma);
// Setup: Create test data
const checkListSet = {
id: 'test-id-2',
name: 'Another Checklist',
description: 'Another Description',
documents: []
};
await repo.storeCheckListSet({ checkListSet });
// Test: Find by ID
const found = await repo.findCheckListSetById('test-id-2');
// Verify
expect(found).not.toBeNull();
expect(found?.name).toBe('Another Checklist');
});
it('should return null for non-existent id', async () => {
const repo = makePrismaCheckRepository(prisma);
const found = await repo.findCheckListSetById('non-existent');
expect(found).toBeNull();
});
});
Running Tests
Run All Tests
cd backend
npm test
Run Specific Test Suite
cd backend
npm run test -- checklist-management
Run Tests in Watch Mode
cd backend
npm run test:watch
Run Tests with Coverage
cd backend
npm run test:coverage
Test Organization
backend/src/api/features/{feature}/__tests__/
├── repository-integration.test.ts # Database integration tests
├── usecase.test.ts # Use case unit tests (mocked repo)
└── handlers.test.ts # Handler unit tests (mocked usecase)
Writing Repository Tests
Best Practices
- Use Actual Database: Never mock Prisma client in repository tests
- Clean Before Each: Use
beforeEachto ensure clean state - Test Real Scenarios: Cover actual database operations
- Verify Data Integrity: Check that data is correctly stored and retrieved
Repository Test Template
import { describe, it, expect, beforeEach, afterAll } from 'vitest';
import { PrismaClient } from '@prisma/client';
import { makeYourRepository } from '../domain/repository';
const prisma = new PrismaClient();
describe('YourRepository Integration Tests', () => {
beforeEach(async () => {
// Clean up test data
await prisma.yourModel.deleteMany();
});
afterAll(async () => {
// Disconnect Prisma client
await prisma.$disconnect();
});
it('should create and retrieve entity', async () => {
const repo = makeYourRepository(prisma);
// 1. Create test entity
const entity = {
id: 'test-1',
name: 'Test Entity',
// ... other fields
};
// 2. Store entity
await repo.storeEntity({ entity });
// 3. Retrieve entity
const retrieved = await repo.findEntityById('test-1');
// 4. Verify
expect(retrieved).not.toBeNull();
expect(retrieved?.name).toBe('Test Entity');
});
it('should update entity', async () => {
const repo = makeYourRepository(prisma);
// Setup
const entity = { id: 'test-2', name: 'Original' };
await repo.storeEntity({ entity });
// Test update
await repo.updateEntity({ id: 'test-2', name: 'Updated' });
// Verify
const updated = await repo.findEntityById('test-2');
expect(updated?.name).toBe('Updated');
});
it('should delete entity', async () => {
const repo = makeYourRepository(prisma);
// Setup
const entity = { id: 'test-3', name: 'To Delete' };
await repo.storeEntity({ entity });
// Test delete
await repo.deleteEntity('test-3');
// Verify
const deleted = await repo.findEntityById('test-3');
expect(deleted).toBeNull();
});
});
Database Management Commands
View Database in Prisma Studio
cd backend
npm run prisma:studio
Access at: http://localhost:5555
Reset Local Database
# From project root
docker-compose -f assets/local/docker-compose.yml down -v
docker-compose -f assets/local/docker-compose.yml up -d
# Re-run migrations
cd backend
npm run prisma:migrate
npm run db:seed
Check Database Connection
cd backend
npx prisma db pull # Test connection and pull schema
Troubleshooting
Database Connection Errors
Error: Can't reach database server at localhost:3306
Solutions:
Check Docker container is running:
docker ps | grep mysqlRestart Docker container:
docker-compose -f assets/local/docker-compose.yml restartCheck MySQL logs:
docker-compose -f assets/local/docker-compose.yml logs mysql
Prisma Client Errors
Error: @prisma/client did not initialize yet
Solution:
cd backend
rm -rf node_modules/.prisma
npm run prisma:generate
Migration Errors
Error: Migration {name} failed
Solutions:
- Check migration file syntax
- Manually fix database schema
- Reset database (development only):
docker-compose -f assets/local/docker-compose.yml down -v docker-compose -f assets/local/docker-compose.yml up -d cd backend && npm run prisma:migrate
Test Timeout Errors
Error: Test timed out
Solutions:
- Increase test timeout in vitest config
- Check database connection is not hanging
- Verify no deadlocks in test setup
Quick Reference
| Task | Command |
|---|---|
| Start DB | docker-compose -f assets/local/docker-compose.yml up -d |
| Stop DB | docker-compose -f assets/local/docker-compose.yml down |
| Reset DB | Add -v flag to down command, then up |
| Generate Prisma | cd backend && npm run prisma:generate |
| Run migrations | cd backend && npm run prisma:migrate |
| Seed data | cd backend && npm run db:seed |
| Run tests | cd backend && npm test |
| Run specific test | cd backend && npm run test -- {test-name} |
| Prisma Studio | cd backend && npm run prisma:studio |
Success Criteria
✅ Database running: Docker container active ✅ Migrations applied: Schema matches Prisma schema ✅ Tests pass: All repository integration tests succeed ✅ Data verified: Prisma Studio shows correct data structure
After Testing
- ✅ All repository tests passed
- ✅ Database operations work correctly
- Ready to run
/build-and-formatfor final verification - Consider running full test suite:
npm test