Previously: In Testing RLS Policies in Supabase, we tested RLS policies with authenticated users. Now let's explore efficient strategies for seeding Supabase test databases with realistic data.
Testing with realistic data reveals edge cases that empty tables hide. Manually inserting data in every test is tedious and error-prone. You need flexible, maintainable ways to populate your Supabase test database that work with RLS policies, auth.users, and Supabase system tables.
In this lesson, you'll learn how to seed Supabase test databases using supabase-test's direct load methods: loadJson(), loadSql(), loadCsv(), and the insertUser() helper.
Prerequisites
See Prerequisites. Requires: Complete Testing RLS Policies in Supabase.
Table of Contents
- Why Seeding Matters in Supabase
- Seeding auth.users with insertUser()
- Seeding with loadJson()
- Seeding with loadSql()
- Seeding with loadCsv()
- Combining Seeding Strategies
- Per-Test Seeding
Why Seeding Matters in Supabase
Testing without proper seeding leads to:
- Verbose tests cluttered with INSERT statements
- Repetitive
auth.userscreation in every test - Unrealistic data that misses edge cases
supabase-test provides insertUser(), loadJson(), loadSql(), and loadCsv() for clean, maintainable test data.
Seeding auth.users with insertUser()
Supabase requires users in auth.users for authenticated operations. The insertUser() helper makes this simple:
Create __tests__/user-seeding.test.ts:
Key Features:
insertUser(pg, email, id?)- Creates users inauth.users- Use
pgclient - Superuser client bypasses RLS for user creation - Returns user object - Contains
id,email, and other user properties
Run the test:
Seeding with loadJson()
The loadJson() method is perfect for inline test data. It's simple, readable, and respects RLS policies.
Create __tests__/json-seeding.test.ts:
Key Features:
- Schema-qualified tables - Use
'pets.pets'to specify the schema - UUID support - Can specify explicit IDs for referential integrity
- RLS-aware - Respects RLS policies (use
pgfor setup,dbfor testing) - Clean syntax - JSON objects map directly to table rows
Seeding with loadSql()
For larger datasets or when you want to version-control fixtures separately, SQL files work well.
Create __tests__/fixtures/pets-fixture.sql:
Create __tests__/sql-seeding.test.ts:
Seeding with loadCsv()
For very large datasets or data exported from spreadsheets, CSV is ideal.
Create __tests__/fixtures/pets.csv:
Create __tests__/csv-seeding.test.ts:
Important CSV Note: loadCsv() uses Postgres's COPY command, which bypasses RLS policies during load. Always use pg (superuser) to load CSV data, not db.
Combining Seeding Strategies
You can mix seeding methods in the same test to leverage each approach's strengths.
Create __tests__/fixtures/users.csv:
Create the test:
Per-Test Seeding
Sometimes different tests need different data. Seed in beforeEach() instead of beforeAll():
Each test gets fresh data thanks to transaction rollback combined with per-test seeding.
Key Takeaways
- insertUser() - Essential helper for creating users in auth.users
- loadJson() - Perfect for inline test data, respects RLS policies
- loadSql() - Ideal for large fixtures and complex SQL operations
- loadCsv() - Fast for huge datasets, but bypasses RLS (use
pgclient) - Transaction isolation - Changes are rolled back between tests automatically
What's Next
You've mastered seeding strategies for Supabase test databases. Next, you'll learn how to automate these tests with GitHub Actions, running your full test suite on every commit and pull request.
