dansan/fixture-handler
Laravel helper for managing fixtures/test data. Load, reset, and organize fixture sets to seed databases quickly during development and automated tests, keeping sample data consistent across environments.
Installation
composer require --dev dansan/fixture-handler
Register the service provider in config/app.php under providers:
Dansan\FixtureHandler\FixtureHandlerServiceProvider::class,
Basic Usage
Place fixtures in database/fixtures/ (e.g., users.json, posts.json).
Define a test case extending Dansan\FixtureHandler\TestCase:
use Dansan\FixtureHandler\TestCase;
class UserTest extends TestCase
{
protected $fixtures = ['users', 'posts'];
public function testUserCreation()
{
$user = User::first();
$this->assertNotNull($user);
}
}
First Run Execute tests with:
php artisan test
Fixtures are auto-loaded before each test method.
database/
├── fixtures/
│ ├── users.json
│ ├── posts.json
│ └── relationships/
│ └── user_posts.json # For polymorphic relationships
roles_and_permissions.json).
Group related fixtures in subdirectories (e.g., database/fixtures/admin/).Seeding vs. Fixtures
Use fixtures for test-specific data (e.g., mock users, edge cases).
Use Laravel’s DatabaseSeeder for shared test data (e.g., default roles).
Dynamic Fixtures Load fixtures conditionally based on test methods:
public function testAdminFeatures()
{
$this->loadFixtures(['admin/users']);
// Test logic...
}
Fixture Factories Combine with Laravel’s factories for dynamic data:
// In a fixture file (users.json)
{
"data": [
{"name": "John", "email": "{{ $this->faker->unique()->safeEmail }}"}
]
}
Test Isolation
Use refreshDatabase() in setUp() to ensure clean state:
public function setUp(): void
{
parent::setUp();
$this->artisan('migrate:fresh');
$this->loadFixtures($this->fixtures);
}
Fixture Dependencies
Define dependencies in a meta.json file:
{
"users": ["roles"],
"posts": ["users"]
}
Load them in order:
$this->loadFixtures(['roles', 'users', 'posts']);
Custom Fixture Loaders
Extend Dansan\FixtureHandler\Loaders\LoaderInterface for custom formats (e.g., YAML):
class YamlLoader implements LoaderInterface
{
public function load(string $path): array
{
return yaml_parse_file($path);
}
}
Register in config/fixture-handler.php:
'loaders' => [
'yaml' => \App\Loaders\YamlLoader::class,
],
Fixture Overwriting
migrate:fresh or refreshDatabase() to reset the database.Missing Dependencies
role_id in users.json).null as a placeholder.JSON Validation
php artisan fixture:validate
Case Sensitivity
User vs. user).snake_case in fixture files and studlyCase in code.Log Fixtures
Enable debug mode in config/fixture-handler.php:
'debug' => true,
Logs fixture loading to storage/logs/fixture-handler.log.
Inspect Loaded Data
Dump fixtures in setUp():
public function setUp(): void
{
parent::setUp();
$this->loadFixtures($this->fixtures);
\Log::info('Loaded fixtures:', $this->getLoadedFixtures());
}
Partial Fixture Loading Load only specific records:
$this->loadFixtures(['users'], ['id' => 1]); // Load only user with ID 1
Custom Database Connections
Specify in config/fixture-handler.php:
'connection' => 'sqlite_testing',
Fixture File Extensions
Supported: .json, .yaml (with custom loader).
Tip: Use .json for consistency.
Performance
loadFixtures() selectively or split into smaller files.Custom Fixture Events
Listen for fixture.loaded events:
\Event::listen('fixture.loaded', function ($fixture) {
\Log::info("Fixture loaded: {$fixture['name']}");
});
Post-Fixture Hooks Run logic after fixtures load:
public function setUp(): void
{
parent::setUp();
$this->loadFixtures($this->fixtures);
$this->afterFixturesLoaded();
}
protected function afterFixturesLoaded()
{
// Example: Seed additional test data
factory(App\Post::class)->create(['user_id' => 1]);
}
Fixture Encryption Encrypt sensitive data (e.g., passwords) in fixtures:
// In a fixture file
{
"password": "{{ bcrypt('secret') }}"
}
Requires use Illuminate\Support\Facades\Hash; in the test class.
How can I help you explore Laravel packages today?