patternphplaravelTip
Database Seeders and Model Factories for Reproducible Test Data
Viewed 0 times
factoryseederfakerstatemakecreateRefreshDatabasetest data
Problem
Tests and local development require consistent, realistic seed data. Hard-coding arrays in seeders is fragile. Using production data dumps in tests is a security and privacy risk.
Solution
Define a ModelFactory for each model using Faker. Use factory states for variant scenarios (e.g., ->published(), ->trashed()). Call factories from seeders with ::factory()->count(50)->create(). Run DatabaseSeeder from tests with RefreshDatabase or use RefreshDatabaseLazily.
Why
Factories generate varied, realistic data without manual maintenance. States let you create specific scenarios without duplicating the entire factory definition. Seeder composition keeps the database in a deterministic state for every test run.
Gotchas
- factory() calls inside seeders bypass model events by default; use afterCreating() callback to trigger them
- Use ::factory()->make() to create a non-persisted instance for unit tests
- Sequences allow cycling through fixed values: new Sequence(['role' => 'admin'], ['role' => 'user'])
- RefreshDatabase wraps each test in a transaction and rolls back—much faster than re-seeding
Code Snippets
Factory with state
class PostFactory extends Factory
{
public function definition(): array
{
return [
'title' => fake()->sentence(),
'status' => 'draft',
];
}
public function published(): static
{
return $this->state(['status' => 'published']);
}
}Revisions (0)
No revisions yet.