[ The sdxc command ]
Make a factory
Write the factory tests seed a model's rows with, through the model itself, with sdxc make factory.
Last updated 2026-10-19
A factory builds complete rows for tests, so a test sets only the fields it is about. It writes
through the model, so callbacks, constraints and meta run in a fixture as they do in production.
sdxc make factory writes one in database/factories/ for the model of the same name:
sdxc make factory post
Wrote database/factories/post.ts
sdxc make model already writes a model's factory, with a
sample value per field. Reach for sdxc make factory for a model made with --skip factory, or
one written by hand.
Flags
| Flag | What it does |
|---|---|
--dry-run | print the file and change nothing |
A factory is test code itself, so it never gets a test beside it.
What it writes
import { defineFactory } from "@sdxc/data-model/testing";
import { Post } from "~/app/models/post";
/** A complete Post row; a test overrides only the fields it is about. */
export const PostFactory = defineFactory(Post, {});
The factory imports the model's PascalCase export from the file of the same name in
app/models/, so sdxc make factory billing/invoice writes database/factories/billing/invoice.ts
reading Invoice from ~/app/models/billing/invoice, the name
sdxc make model exports. With no fields to read, the attributes start
empty for you to fill.
Fill it in
Give every column the model requires a value, drawn from the sample streams so each row differs and a seed reproduces a run:
export const PostFactory = defineFactory(Post, {
title: ({ sample }) => sample.lorem.sentence(),
body: ({ sample }) => sample.lorem.paragraph(),
published_at: () => Date.now(),
author_id: async ({ create }) => (await create(AuthorFactory)).id,
}).trait("draft", { published_at: null });
Then create rows in a test:
let factories = createFactories(models, { seed: 42 });
let post = await factories.create(PostFactory, { title: "Hello" });
await factories.createMany(PostFactory, 3);
Data models covers traits, sequences and the in-memory database a test binds the models to, and Test data seeding beyond one model.
Where to go next
Make a model — the model a factory writes through.
Make a migration — the table the rows land in.
Generate files — the flags, configuration and stubs every kind shares.