Mahamudul Hasan Rubel
HomeBlogCoursesAboutProjectsSkillsExperiencePhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • Blog
  • Courses
  • About
  • Projects
  • Skills
  • Experience
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

Subscribe to the newsletter

Get new articles and course lessons delivered to your inbox. No spam, unsubscribe anytime.

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
Lesson 19 of the Intermediate Laravel: Real-World Application Patterns course
LaravelJune 26, 20263 min read

Mastering Laravel Database Factories and Seeding for Testing

Learn to master Laravel database factories and seeders to generate realistic test data. Create state modifiers and automate your testing workflow efficiently.

LaravelTestingDatabaseFactoriesSeedingphpbackend

Previously in this course, we explored Testing Events and Jobs in Laravel: A Guide to Reliable Systems to ensure our background processes behave as expected. While testing async tasks is vital, those tests often fail if the underlying database lacks the necessary structure or relational data. In this lesson, we move beyond manual inserts and hardcoded IDs by mastering database factories and seeders to build a robust, reproducible testing environment for our project board.

Understanding Factories and Seeding

At the intermediate level, you shouldn't be manually creating users or tasks in every test file. Doing so leads to "brittle" tests—where changing a column name in your migration forces you to rewrite dozens of test cases.

Laravel's factories act as blueprints for your models. They use the faker library to generate realistic data (names, emails, timestamps) automatically. Seeders, on the other hand, are the orchestrators; they use these factories to populate your database with initial state, whether for development, staging, or integration testing.

Creating Model Factories

Let’s advance our project board by creating a factory for our Task model. Run php artisan make:factory TaskFactory.

In your database/factories/TaskFactory.php, you define the default state. This ensures that every time you call Task::factory(), you get a valid, persisted database record.

PHP
public function definition(): array
{
    return [
        'title' => fake()->sentence(),
        'description' => fake()->paragraph(),
        'status' => 'pending',
        'user_id' => \App\Models\User::factory(), #6A9955">// Automatically creates a user
        'due_at' => fake()->dateTimeBetween('now', '+1 month'),
    ];
}

Notice how user_id calls the User::factory(). Laravel is smart enough to handle these nested relationships automatically, ensuring that when you create a task, a parent user is created alongside it.

Using State Modifiers

One of the most powerful features of factories is the ability to define "states." Instead of manually overriding attributes in every test, define a named state in your factory:

PHP
public function overdue(): static
{
    return $this->state(fn(array $attributes) => [
        'due_at' => now()->subDay(),
        'status' => 'pending',
    ]);
}

Now, in your feature tests, you can write expressive, readable code:

PHP
#6A9955">// In your test file
$task = Task::factory()->overdue()->create();

$this->getJson('/api/tasks')
    ->assertJsonFragment(['status' => 'pending']);

Writing Database Seeders

While factories are for individual records, seeders are for populating the application state. Use them to set up admin users, default categories, or initial project boards.

Open database/seeders/DatabaseSeeder.php. You should use seeders to call other specific seeders to keep your logic clean:

PHP
public function run(): void
{
    #6A9955">// Create 10 users, each with 3 tasks
    \App\Models\User::factory(10)
        ->has(Task::factory()->count(3))
        ->create();
}

Hands-on Exercise: Populating the Project Board

Your task is to prepare the database for our project board.

  1. Create a ProjectSeeder that generates 5 projects.
  2. For each project, ensure it has a team of 3 users (one owner, two members).
  3. Use the has() method on your User factory to attach tasks to these users.
  4. Run php artisan db:seed.

This ensures that whenever you pull down the code, you have a fully functional environment ready for development.

Common Pitfalls

  1. Over-reliance on create(): Use make() when you only need an object instance and don't need to hit the database. It is significantly faster for unit tests.
  2. Ignoring Relationships: Don't manually set user_id => 1 in tests. Always use factories (user_id => User::factory()) so the test remains decoupled from specific database IDs.
  3. Hardcoding Data: Use fake() for everything. If you hardcode 'Task Title', you might miss edge cases where a user enters a 255-character string or special characters that break your UI.
  4. Massive Seeders: Keep your DatabaseSeeder clean. If you have complex setup logic, move it into specific classes like ProjectSeeder or DemoDataSeeder.

Recap

We’ve covered the fundamentals of generating consistent, realistic data. By leveraging factories and states, we've moved away from fragile, hardcoded tests toward a system that evolves with our schema. Seeders provide the final piece of the puzzle, ensuring our development environment is always ready for action.

Up next: We will explore API Versioning Strategies to ensure our project board can evolve without breaking existing client integrations.

Previous lessonTesting Events and JobsNext lesson API Versioning Strategies
Back to Blog

Similar Posts

LaravelJune 28, 20264 min read

Advanced Database Migration Strategies for Laravel

Master non-breaking migrations and safe rollback procedures. Learn the expand-and-contract pattern to evolve your database schema without production downtime.

Read more
LaravelJune 28, 20263 min read

Database Query Caching Layers: Optimizing Laravel Performance

Learn how to implement database query caching in Laravel to reduce server load. Master cache eviction strategies to ensure data integrity in high-traffic apps.

Part of the course

Intermediate Laravel: Real-World Application Patterns

intermediate · Lesson 19 of 58

  1. 1

    Architecting for Maintainability

    3 min
  2. 2

    Implementing the Service Layer

    3 min
  3. 3

    Repository Pattern Fundamentals

    3 min
Read more
LaravelJune 28, 20263 min read

Contract Testing: Automating Modular Monolith Interfaces in Laravel

Master contract testing in Laravel to ensure your decoupled modules stay compatible. Learn to implement consumer-driven contracts to prevent breaking changes.

Read more
  • 4

    Project Board Domain Modeling

    3 min
  • 5

    Advanced Eloquent Scopes and Accessors

    4 min
  • 6

    Service-Oriented Task Management

    3 min
  • 7

    REST API Fundamentals with Sanctum

    3 min
  • 8

    Resource Controllers and API Responses

    3 min
  • 9

    Handling API Validation and Form Requests

    3 min
  • 10

    Implementing Middleware for API Security

    4 min
  • 11

    Database Transactions for Data Integrity

    3 min
  • 12

    Error Handling and Global Exceptions

    3 min
  • 13

    Introduction to Laravel Events and Listeners

    3 min
  • 14

    Asynchronous Processing with Queues

    4 min
  • 15

    Job Chaining and Batching

    3 min
  • 16

    Feature Testing Fundamentals

    4 min
  • 17

    Mocking Services and Repositories in Tests

    3 min
  • 18

    Testing Events and Jobs

    3 min
  • 19

    Database Factories and Seeding

    3 min
  • 20

    API Versioning Strategies

    4 min
  • 21

    Advanced Request Filtering and Sorting

    3 min
  • 22

    Handling File Uploads in REST APIs

    3 min
  • 23

    Real-time Notifications with Broadcasting

    3 min
  • 24

    Using Observers for Model Lifecycle Hooks

    3 min
  • 25

    Implementing Policies for Authorization

    3 min
  • 26

    Customizing Authentication Guards

    3 min
  • 27

    Rate Limiting API Endpoints

    4 min
  • 28

    Eloquent Performance Optimization

    4 min
  • 29

    Caching Strategies for Performance

    4 min
  • 30

    Using Traits for Code Reuse

    3 min
  • 31

    Advanced Dependency Injection with Service Providers

    3 min
  • 32

    Command Line Tools with Artisan

    3 min
  • 33

    Scheduled Tasks and Cron Jobs

    3 min
  • 34

    Integrating Third-Party Services

    3 min
  • 35

    Handling Webhooks

    3 min
  • 36

    Logging and Monitoring

    3 min
  • 37

    Database Migrations Best Practices

    3 min
  • 38

    Advanced Testing: Integration Tests

    4 min
  • 39

    Testing API Authentication

    4 min
  • 40

    Code Quality and Static Analysis

    3 min
  • 41

    Project Structure for Large Applications

    3 min
  • 42

    Environment and Configuration Management

    3 min
  • 43

    Deploying Laravel Applications

    4 min
  • 44

    Database Indexing Strategies

    4 min
  • 45

    Using Value Objects

    4 min
  • 46

    Strategy Pattern for Business Rules

    3 min
  • 47

    Advanced Queue Monitoring

    3 min
  • 48

    Building a Search API

    3 min
  • 49

    Handling Concurrency and Race Conditions

    4 min
  • 50

    API Documentation with OpenAPI

    3 min
  • 51

    Testing with Test Doubles

    3 min
  • 52

    Implementing Multi-Tenancy

    4 min
  • 53

    Refactoring Legacy Code

    4 min
  • 54

    Using Middleware for Feature Flags

    3 min
  • 55

    Building Reusable Packages

    4 min
  • 56

    Performance Profiling

    3 min
  • 57

    Secure API Design

    3 min
  • 58

    Event Sourcing Concepts

    4 min
  • View full course