Laravel Factory Relationship Control: Precise Test Data Management

Laravel Factory Relationship Control: Precise Test Data Management

Laravel factories are fantastic for testing, but sometimes they create too much data by automatically expanding relationships you don't actually need. The new dontExpandRelationshipsByDefault() method gives you precise control over what gets created.

When writing tests, you often need specific model instances without the overhead of creating all their related models. Laravel's factory relationship expansion control allows you to toggle whether factories automatically create parent relationships, giving you cleaner, more focused test data.

The Problem It Solves

By default, Laravel factories can create a cascade of related models when you only need the primary model for your test. This leads to unnecessary database records, slower test execution, and potential interference between test cases.

Previously, you had to work around this by manually specifying which relationships to exclude or include, leading to verbose and repetitive test setup code.

Real-World Example

Consider testing a permission system where you need specific UserPermission models without creating the associated User, Company, or Product records:

public function test_has_one_editor_permission_returns_true(): void
{
    UserPermissionFactory::dontExpandRelationshipsByDefault();
    
    $collection = new UserPermissionCollection([
        UserPermission::factory()
            ->withoutParents()
            ->make([
                'type' => 'viewer',
                'company_id' => 2,
                'product_id' => 789,
            ]),
        UserPermission::factory()
            ->withoutParents()
            ->make([
                'type' => 'editor',
                'company_id' => 2,
                'product_id' => 432,
            ]),
    ]);
    
    $result = $collection->hasEditorForCompany(2);
    
    $this->assertTrue($result);
}

This approach creates only the UserPermission models you need for testing the collection's logic, without the overhead of creating users, companies, or products.

Method Control

Laravel provides two complementary methods to control relationship expansion:

UserPermissionFactory::dontExpandRelationshipsByDefault();

UserPermissionFactory::expandRelationshipsByDefault();

You can toggle this behavior throughout your test suite as needed. When relationships are disabled by default, you can still create specific relationships using the factory's relationship methods when required.

The relationship expansion control transforms factory usage from a potentially heavy operation into a surgical tool that creates exactly what your tests need. This leads to faster, more focused tests that clearly communicate their intent while avoiding the complexity of managing unnecessary related data.


Stay Updated with More Laravel Tips

Enjoyed this article? There's plenty more where that came from! Subscribe to our channels to stay updated with the latest Laravel tips, tricks, and best practices:

Subscribe to Harris Raftopoulos

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe