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:
- Follow us on Twitter @harrisrafto
- Join us on Bluesky @harrisrafto.eu
- Subscribe to our YouTube channel @harrisrafto