Factories
- Creating a Factory
- Integrating with Your Model
- Using Factories in Tests
- Faker Integration
- Testing Example
- Learn More
Model factories allow you to generate realistic test data quickly and consistently. UserFrosting uses Laravel's Eloquent factory system with a custom base class.
Creating a Factory
Model factories must extend UserFrosting\Sprinkle\Core\Database\Factories\Factory. The factory should be named after your model with a "Factory" suffix (e.g., UserFactory for the User model).
Example Factory:
<?php
namespace App\MySite\Database\Factories;
use App\MySite\Database\Models\Article;
use UserFrosting\Sprinkle\Core\Database\Factories\Factory;
class ArticleFactory extends Factory
{
protected $model = Article::class;
public function definition(): array
{
return [
'title' => $this->faker->sentence(),
'content' => $this->faker->paragraphs(3, true),
'published' => true,
'created_at' => $this->faker->dateTimeBetween('-1 year', 'now'),
];
}
}
Integrating with Your Model
Your model needs two things to work with factories:
- Use the
HasFactorytrait - Define a
newFactorymethod
<?php
namespace App\MySite\Database\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use UserFrosting\Sprinkle\Core\Database\Models\Model;
class Article extends Model
{
use HasFactory;
/**
* Create a new factory instance for the model.
*/
protected static function newFactory()
{
return ArticleFactory::new();
}
}
Using Factories in Tests
Creating Single Models
// Create one article and save it to the database
$article = Article::factory()->create();
// Create an article but don't save it
$article = Article::factory()->make();
Creating Multiple Models
// Create 10 articles
$articles = Article::factory()->count(10)->create();
Overriding Attributes
// Override specific attributes
$article = Article::factory()->create([
'title' => 'Custom Title',
'published' => false,
]);
Factory States
Define different states for your models:
class ArticleFactory extends Factory
{
// ... definition method ...
public function draft(): static
{
return $this->state(fn (array $attributes) => [
'published' => false,
]);
}
public function featured(): static
{
return $this->state(fn (array $attributes) => [
'featured' => true,
]);
}
}
Use states in tests:
// Create a draft article
$draft = Article::factory()->draft()->create();
// Chain multiple states
$featuredDraft = Article::factory()->draft()->featured()->create();
Factory Relationships
Create related models together:
// Create an article with a specific user
$article = Article::factory()
->for($user)
->create();
// Create multiple comments for an article
$article = Article::factory()
->has(Comment::factory()->count(3))
->create();
Sequences
Generate progressive data:
use Illuminate\Database\Eloquent\Factories\Sequence;
// Create articles with sequential titles
$articles = Article::factory()
->count(3)
->state(new Sequence(
['title' => 'First Article'],
['title' => 'Second Article'],
['title' => 'Third Article'],
))
->create();
// Sequence with index
$articles = Article::factory()
->count(5)
->state(new Sequence(
fn ($sequence) => ['title' => 'Article ' . $sequence->index],
))
->create();
Faker Integration
Factories have access to Faker through $this->faker for generating realistic random data:
public function definition(): array
{
return [
'title' => $this->faker->sentence(),
'slug' => $this->faker->slug(),
'content' => $this->faker->paragraphs(3, true),
'author' => $this->faker->name(),
'email' => $this->faker->safeEmail(),
'views' => $this->faker->numberBetween(0, 10000),
'rating' => $this->faker->randomFloat(2, 1, 5),
'tags' => $this->faker->words(3),
'published' => $this->faker->boolean(80), // 80% chance of true
];
}
Testing Example
Here's a complete example using factories in a test:
<?php
namespace App\MySite\Tests\Database\Models;
use App\MySite\Database\Models\Article;
use App\MySite\Database\Models\User;
use App\MySite\Tests\MySiteTestCase;
use UserFrosting\Sprinkle\Core\Testing\RefreshDatabase;
class ArticleTest extends MySiteTestCase
{
use RefreshDatabase;
public function setUp(): void
{
parent::setUp();
$this->refreshDatabase();
}
public function testArticleCreation(): void
{
$user = User::factory()->create();
$article = Article::factory()
->for($user)
->create(['title' => 'Test Article']);
$this->assertSame('Test Article', $article->title);
$this->assertSame($user->id, $article->user_id);
}
}
Learn More
For complete details on factory capabilities, see the Laravel Eloquent Factories documentation.