Skip to main content
Learn how to sync Fixture DB data to Test DB to prepare the test environment.

Fixture Sync Overview

Complete Copy

All data Schema + Records

Clean Start

Test DB initialization Consistent environment

Fast Execution

pg_dump + pg_restore Efficient copy

Auto Execution

Auto after import Manual also available

pnpm sonamu fixture sync

Copies all data from Fixture DB to Test DB.

Basic Usage

pnpm sonamu fixture sync
This command:
  1. Completely initializes Test DB
  2. Dumps Fixture DB
  3. Restores to Test DB

How It Works

Internal Implementation

// sonamu/src/testing/fixture-manager.ts
async function sync() {
  const fixtureConn = Sonamu.dbConfig.fixture.connection;
  const testConn = Sonamu.dbConfig.test.connection;

  // 1. Terminate Test DB connections
  execSync(`psql -h ${testConn.host} -p ${testConn.port} -U ${testConn.user} 
    -d postgres -c "
      SELECT pg_terminate_backend(pg_stat_activity.pid)
      FROM pg_stat_activity
      WHERE datname = '${testConn.database}'
        AND pid <> pg_backend_pid();
    "`);

  // 2. Recreate Test DB
  execSync(`psql -h ${testConn.host} -U ${testConn.user} -d postgres 
    -c "DROP DATABASE IF EXISTS \\"${testConn.database}\\""`);

  execSync(`psql -h ${testConn.host} -U ${testConn.user} -d postgres 
    -c "CREATE DATABASE \\"${testConn.database}\\""`);

  // 3. Fixture DB → Test DB copy
  const dumpCmd = `pg_dump -h ${fixtureConn.host} -p ${fixtureConn.port} 
    -U ${fixtureConn.user} -d ${fixtureConn.database} -Fc`;

  const restoreCmd = `pg_restore -h ${testConn.host} -p ${testConn.port} 
    -U ${testConn.user} -d ${testConn.database} --no-owner --no-acl`;

  execSync(`${dumpCmd} | PGPASSWORD="${testConn.password}" ${restoreCmd}`);
}

Execution Process

$ pnpm sonamu fixture sync

# 1. Terminate existing connections
Terminating existing connections to myapp_test...

# 2. Recreate Test DB
DROP DATABASE IF EXISTS "myapp_test"
CREATE DATABASE "myapp_test"

# 3. Dump Fixture DB
pg_dump -h fixture-db.example.com -d myapp_fixture -Fc

# 4. Restore to Test DB
pg_restore -h localhost -d myapp_test --no-owner --no-acl

 Sync complete!

Usage Scenarios

1. After Fixture Changes

# Add new data to Fixture
pnpm sonamu fixture import User 10,11,12

# Sync runs automatically
# But manual is also possible:
pnpm sonamu fixture sync

2. Test DB Initialization

# When Test DB is polluted
# (e.g., manually added data)
pnpm sonamu fixture sync

# Reset to clean Fixture data

3. Team Synchronization

# Team member A adds data to Fixture
# (saved to remote Fixture DB)

# Team member B syncs to local Test DB
pnpm sonamu fixture sync

Database Comparison

pg_dump Options

-Fc (Format Custom)

Dumps in binary format for speed and efficiency.
# -Fc: Custom format (compressed binary)
pg_dump -d myapp_fixture -Fc
Benefits:
  • Compressed, smaller size
  • Selective restore possible with pg_restore
  • Fast speed

—no-owner —no-acl

Excludes owner and permission information.
pg_restore -d myapp_test --no-owner --no-acl
Reason:
  • Users may differ between local and remote
  • Prevents permission conflicts

Auto vs Manual

Auto Sync

Sync is automatically called when running pnpm sonamu fixture import:
async function fixture_import(entityId: string, recordIds: number[]) {
  await setupFixtureManager();

  // 1. Import
  await FixtureManager.importFixture(entityId, recordIds);

  // 2. Sync (auto)
  await FixtureManager.sync();
}
$ pnpm sonamu fixture import User 1,2,3

# After import completes, automatically:
 Import complete! Syncing to test DB...
# Sync runs...

Manual Sync

Run directly when needed:
# Reset Test DB to Fixture DB state
pnpm sonamu fixture sync

Workflow

Typical Development Flow

# 1. Import necessary data from production
pnpm sonamu fixture import User 1,2,3
# → Sync runs automatically

# 2. Run tests
pnpm test

# 3. Import additional data if needed
pnpm sonamu fixture import Post 10,11,12
# → Sync runs automatically

# 4. Re-run tests
pnpm test

Fixture Sharing Flow

# Team member A
pnpm sonamu fixture import User 100,101,102
# → Saved to Fixture DB (remote)

# Team member B
pnpm sonamu fixture sync
# → Copy from Fixture DB to local Test DB

# Team member B can now test with same data

Performance Optimization

1. Local Fixture DB

Sync is faster when running Fixture DB locally:
// sonamu.config.json
{
  "db": {
    "fixture": {
      "client": "pg",
      "connection": {
        "host": "localhost", // Local
        "database": "myapp_fixture"
      }
    },
    "test": {
      "client": "pg",
      "connection": {
        "host": "localhost",
        "database": "myapp_test"
      }
    }
  }
}

2. Minimal Data

Keep only necessary data in Fixture:
# ✅ Correct: Only what's needed
pnpm sonamu fixture import User 1,2,3

# ❌ Wrong: Too much data
pnpm sonamu fixture import User 1,2,3,...,1000

Best Practices

1. Regular Sync

# Sync to latest Fixture every morning
pnpm sonamu fixture sync

# Run tests
pnpm test

2. CI/CD Integration

# .github/workflows/test.yml
name: Test

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: Setup PostgreSQL
        run: |
          docker run -d -p 5432:5432 \
            -e POSTGRES_PASSWORD=postgres \
            postgres:14

      - name: Initialize Fixture
        run: pnpm sonamu fixture init

      - name: Sync Fixture
        run: pnpm sonamu fixture sync

      - name: Run Tests
        run: pnpm test

3. Add Scripts

// package.json
{
  "scripts": {
    "test:setup": "pnpm sonamu fixture sync",
    "test": "pnpm test:setup && vitest"
  }
}
# Auto sync before test
pnpm test

Troubleshooting

Connection Failed

Error: connection to server at "fixture-db.example.com" failed
Solution:
  • Check network connection
  • Check Fixture DB server status
  • Check firewall settings

Permission Error

Error: must be owner of database myapp_test
Solution:
-- Change Test DB owner
ALTER DATABASE myapp_test OWNER TO current_user;

DB In Use

Error: database "myapp_test" is being accessed by other users
Solution:
-- Terminate all connections
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE datname = 'myapp_test'
  AND pid <> pg_backend_pid();
Or:
# Stop application and try again
pnpm sonamu fixture sync

Cautions

Cautions when syncing fixtures: 1. Test DB initialization: All existing data will be deleted 2. Permissions required: DROP/CREATE permissions for Test DB 3. Connection termination: Will fail if tests are running 4. Network: Takes time if Fixture DB is remote 5. Data size: Sync is slow if Fixture is large

Next Steps

Test DB

Test DB setup

Creating Fixtures

Writing fixture.ts

Loading Fixtures

Import production data

Writing Tests

Understanding test structure