Skip to main content
The pnpm fixture command manages consistent data sets for testing. You can copy actual data from the development environment to the test environment for stable and repeatable tests.

Basic Concept

Fixture is a fixed data set for testing:
  • Consistency: All tests start with the same initial data
  • Isolation: Separate test DB from development DB
  • Reproducibility: Repeatable tests under same conditions
  • Relationship preservation: Foreign key relationships maintained

Commands

init - Initialize Test DB

Copy development DB schema to test DB.
Execution process:
Databases created:
  • Fixture DB (remote): Shared fixture storage
  • Test DB (local): Local testing DB
init copies schema only. Data is not included.

import - Import Data

Save specific records from development DB as fixtures.
Interactive prompt appears:
Related data automatically included:
  • Records referenced by foreign keys
  • Relationship table records
  • Reverse reference records (optional)

sync - Synchronize

Apply saved fixtures to test DB.
Execution process:
Calling sync before test execution ensures you always start with a clean state.

gen - Auto Fixture Generation

Automatically generate fixtures using Entity’s cone metadata. Useful when you don’t have real data or need virtual test data.
Interactive mode:
The generation method prompt is only shown when User entity is included in the selection. If User entity is not selected, the flow proceeds directly to the save method selection.
Loginable User Fixture Generation: When you select the User entity and choose β€œGenerate loginable user fixtures”, the system creates actually loginable users through better-auth’s sign-up/email endpoint. How this mode works:
  1. FixtureGenerator generates User data (name, email, username, etc.)
  2. Calls better-auth sign-up API via Sonamu.auth.handler() to register users
  3. Automatically updates email_verified to true for all created users
  4. Outputs the list of created credentials (email, password) to the console
All generated users share the same password Test1234!. This feature is intended for development/test environments only and should never be used against a production database.
Selecting β€œGenerate dummy data (not loginable)” uses the existing generateBatch() flow to insert data directly into the DB. In this case, no better-auth authentication records are created, so login is not possible. CLI options: Save methods:
  • db: Save directly to Fixture DB (default)
  • file: Save to test/fixtures/{entity_table}.json file
  • file:{filename}: Save with specified filename
  • none: Don’t save, just output to console
Value generation priority: When generating a value for each field, the following strategies are applied in order. The first matching strategy is used, and subsequent steps are skipped.
  1. Relation β€” Fields with foreign key relationships automatically create/reference related records.
  2. cone.note + LLM β€” When --use-llm is enabled and the field’s cone has a note defined, LLM generates realistic values based on the note content. Falls back to the next step if LLM call fails.
  3. cone.fixtureGenerator β€” If the cone has a fixtureGenerator (Faker expression, etc.), it is executed.
  4. cone.fixtureDefault β€” If the cone has a fixtureDefault fixed value, it is used.
  5. Type-based default generation β€” If none of the above strategies apply, values are auto-generated based on the field type (string, number, date, etc.).
When using --use-llm, LLM takes priority over fixtureGenerator for fields with cone.note. This allows generating more realistic, domain-appropriate data.
If an LLM-generated string exceeds the field’s length constraint, it is automatically truncated. For example, if LLM generates 120 characters for a varchar(100) field, only the first 100 characters are used.
Automatic Companion Fixture Generation: When an Entity’s cone has fixtureCompanions declared, companion Entity fixtures are automatically created alongside the parent fixture. For example, in a better-auth based project, generating a User fixture will also automatically create a credentials Account. fixtureCompanions is declared in the Entity’s id prop cone:
To retroactively add fixtureCompanions to existing better-auth projects:
This command automatically adds fixtureCompanions configuration to better-auth Entities (such as User) in their entity.json, only when the configuration does not already exist. Entities that already have the configuration are skipped. parentId Entity Fixture Generation: Entities with parentId (subtypes in an inheritance relationship) are handled specially during gen. Instead of creating new parent records, the generator finds existing parent records in the DB that don’t yet have a corresponding subtype row, and uses those IDs. For example, if Paper is a subtype of Achievement (parentId: "Achievement"):
  1. Queries the achievements table for IDs that don’t have a corresponding row in the papers table
  2. Creates Paper fixtures with those IDs, forming the parent-child relationship
To add conditions when querying parents, specify fixtureParentOverrides in the id prop’s cone:
If there are not enough parent records without a subtype row, fixture generation for that entity is skipped. Make sure to generate sufficient parent entity fixtures beforehand.

fetch - Fetch Data from Production DB

Fetch data from actual production (or development) DB and save to Fixture DB. Use when you need realistic test data.
Interactive mode:
CLI options: Data selection strategies:
  • recent (default): Fetch most recent data first
  • sample: Random sampling
Features:
  • Related data is automatically fetched together (up to depth level 2)
  • Foreign key referential integrity maintained

explore - Query DB Data

Query only DB data. Useful for quickly checking data without saving.
Interactive mode:
CLI options: Data selection strategies:
  • sample (default): Random sample
  • recent: Most recent data
  • random: Completely random
  • ids: Specify specific IDs
  • query: Custom query

Usage Workflow

1. Initial Setup

Run once when starting the project.

2. Select Needed Data

Import actual data needed for testing.

3. Write Tests

user.model.test.ts

4. Run Tests

Fixtures are automatically synced each time tests run.

Fixture Files

Storage Location

File Format

src/fixtures/users.json
Features:
  • JSON format
  • Separate files per Entity
  • Related data automatically included
  • Version controlled with Git

Relationship Data Handling

Automatic Foreign Key Inclusion

When importing a Post, connected Users are automatically included.

N:M Relationship Handling

Many-to-many relationship tables are also automatically included.

Test Isolation

Reset Before Each Test

Isolation effect:
  • Each test is independent
  • Test order doesn’t matter
  • Parallel execution possible

Transaction Isolation

Practical Examples

Complex Relationship Testing

Specific Scenario Data

Troubleshooting

Fixture DB Connection Failed

Problem: Cannot access remote fixture DB
Solution:
.env.test

Missing Relationship Data

Problem: Foreign key error occurs
Solution:

Fixture Conflict

Problem: ID duplication
Solution:

Best Practices

1. Minimal Data

2. Meaningful Data

3. Version Control

4. CI/CD Integration

.github/workflows/test.yml

Next Steps

Testing

Learn about Naite test framework

migrate

Manage migrations