codenco-dev/eloquent-model-tester
Laravel dev-only helper to test Eloquent models: verify table structure/columns, fillable vs guarded attributes, and model relationships. Works with PHPUnit and model factories, integrates easily in your model test classes.
Strengths:
assertHasColumns()->assertHasRelation()) improve readability and maintainability of test suites.Gaps:
RefreshDatabase for stateful tests; lacks built-in support for isolated unit tests without a database.Laravel Ecosystem Fit:
TestCase, RefreshDatabase, and factories. Integrates with PestPHP (via HasModelTester trait) and PHPUnit.assertHasHasManyRelation), which may need setup if not already in place.--dev), making it ideal for CI pipelines.Migration Path:
Schema::hasColumn() checks or assertDatabaseHas() with fluent assertions. Example:
// Before
$this->assertDatabaseHas('users', ['email' => 'test@example.com']);
Schema::connection($this->app->databaseConnection)->hasColumn('users', 'email');
// After
$this->modelTestable(User::class)
->assertHasColumns(['email'])
->assertCanOnlyFill(['name', 'email']);
Minor Risks:
assertHasOnlyColumns() may fail due to temporary schema drift (e.g., migrations running out of order). Mitigate with transactional tests (RefreshDatabase).user_id for belongsTo). Custom keys require explicit overrides, risking human error.assertHasSoftDeleteTimestampColumns() assumes deleted_at is the column name; may need adjustment for custom soft-delete columns.Critical Risks:
Team Maturity:
RefreshDatabase? If not, adoption may require additional setup.author_id instead of user_id) that would need frequent overrides?Test Coverage Strategy:
Performance Impact:
Long-Term Maintenance:
Customization Needs:
HasModelTester trait.TestCase (trait compatibility).Phase 1: Schema Validation
Schema::hasColumn() checks with assertHasColumns().// Before
public function test_user_table_schema()
{
Schema::connection($this->app->databaseConnection)
->assertHasColumn('users', 'email')
->assertHasColumn('users', 'password');
}
// After
public function test_user_model_schema()
{
$this->modelTestable(User::class)
->assertHasColumns(['email', 'password'])
->assertHasOnlyColumnsInFillable(['email']);
}
Phase 2: Relation Testing
public function test_user_relations()
{
$this->modelTestable(User::class)
->assertHasHasManyRelation(Post::class)
->assertHasBelongsToRelation(Profile::class, 'profile', 'user_id');
}
Phase 3: Scoping and Pivots
public function test_user_scopes()
{
$this->modelTestable(User::class)
->assertHasScope('active')
->assertHasScope('withRole');
}
Phase 4: Full Test Suite Refactor
*Test classes (e.g., UserModelTest, PostModelTest).RefreshDatabase trait globally (via tests/TestCase.php) to avoid repetition.--dev dependency).php artisan make:model -mf).RefreshDatabase in tests/TestCase.php (optional but recommended).User, Post) to validate ROI.RefreshDatabase or transactions).assertCanOnlyFill()).HasModelTester; risk of forgetting in new test files.email missing in fillable array").RefreshDatabase), reducing environmental issues.How can I help you explore Laravel packages today?