Testing Prisma Applications
1. Setting Up Test Database
| Strategy | Detail |
|---|---|
| Docker Postgres | Per-CI ephemeral DB |
| SQLite memory | file::memory:?cache=shared |
| Branching | Neon/PlanetScale branches |
2. Mocking Prisma Client
import { mockDeep, DeepMockProxy } from "jest-mock-extended";
import { PrismaClient } from "@prisma/client";
export const prismaMock = mockDeep<PrismaClient>() as DeepMockProxy<PrismaClient>;
| Tool | Detail |
|---|---|
| jest-mock-extended | Type-safe deep mocks |
| vitest-mock-extended | Vitest equivalent |
3. Using Test Containers
| Library | Detail |
|---|---|
| testcontainers | Spawn Postgres container |
| Lifecycle | start → migrate → run tests → stop |
4. Implementing Integration Tests
beforeAll(async () => { await prisma.$executeRawUnsafe(`TRUNCATE "User" CASCADE`); });
test("creates user", async () => {
const u = await prisma.user.create({ data: { email: "a@b.io" } });
expect(u.id).toBeDefined();
});
| Pattern | Detail |
|---|---|
| Truncate | Fast reset between suites |
| Transactional | Begin/rollback per test |
5. Using Transactional Tests
| Aspect | Detail |
|---|---|
| Pattern | Wrap test in $transaction + throw to rollback |
| Caveat | Code under test cannot start its own tx |
6. Seeding Test Data
| Approach | Detail |
|---|---|
| Factories | Per-test custom data |
| Fixtures | Static JSON |
| Seed script | Shared baseline |
7. Cleaning Test Data
| Method | Detail |
|---|---|
| TRUNCATE CASCADE | Fastest for PG |
| deleteMany | Portable across DBs |
| Drop+migrate | Heavy but pristine |
8. Testing Migrations
| Practice | Detail |
|---|---|
| CI run | migrate deploy on shadow DB |
| Round-trip | diff old→new yields no drift |
9. Implementing E2E Tests
| Tool | Detail |
|---|---|
| Playwright | Browser-driven |
| Supertest | HTTP-level |
| Ephemeral env | Docker compose |
10. Using Coverage Tools
| Tool | Detail |
|---|---|
| c8 | Native V8 coverage |
| vitest --coverage | Built-in via c8/istanbul |
| Codecov | SaaS reporting |