PHPackages                             codenco-dev/eloquent-model-tester - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. codenco-dev/eloquent-model-tester

ActiveLibrary[Database &amp; ORM](/categories/database)

codenco-dev/eloquent-model-tester
=================================

Test easier your Eloquent Models in your Laravel Project

v4.0.0(5mo ago)208.3k↓50%1[2 issues](https://github.com/codenco-dev/eloquent-model-tester/issues)1MITPHPPHP ^8.0

Since Jun 1Pushed 5mo ago1 watchersCompare

[ Source](https://github.com/codenco-dev/eloquent-model-tester)[ Packagist](https://packagist.org/packages/codenco-dev/eloquent-model-tester)[ Docs](https://github.com/thomasdominic/eloquent-model-tester)[ RSS](/packages/codenco-dev-eloquent-model-tester/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (3)Versions (18)Used By (1)

Helper for Testing structures, relations of your models in Laravel
==================================================================

[](#helper-for-testing-structures-relations-of-your-models-in-laravel)

[![Latest Version on Packagist](https://camo.githubusercontent.com/fc604430b027dc36311197b9fcb23cd37171b348c866ebdfe354af4fde5e67d7/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f636f64656e636f2d6465762f656c6f7175656e742d6d6f64656c2d7465737465722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/codenco-dev/eloquent-model-tester)[![StyleCI](https://camo.githubusercontent.com/2467ada1230cd91eb86d2f228e9740703aed9398cf5259eba27c54582252a9be/68747470733a2f2f6769746875622e7374796c6563692e696f2f7265706f732f3236383531353832372f736869656c643f6272616e63683d6d6173746572)](https://github.styleci.io/repos/268515827)[![Build Status](https://camo.githubusercontent.com/d7bb547894042c880f569f201c8d375a8806582aec1478ff3373a6edd3e9409d/68747470733a2f2f7472617669732d63692e636f6d2f636f64656e636f2d6465762f656c6f7175656e742d6d6f64656c2d7465737465722e7376673f6272616e63683d6d6173746572)](https://travis-ci.com/thomasdominic/eloquent-model-tester)[![Quality Score](https://camo.githubusercontent.com/7953026e03738eb0b92b3452128d98b857d7bd374571dc3051ea84c2500a24ce/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f636f64656e636f2d6465762f656c6f7175656e742d6d6f64656c2d7465737465722f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/thomasdominic/eloquent-model-tester)[![Total Downloads](https://camo.githubusercontent.com/b38784d13b8663569ca4720a06baddeac12cbc56e9e28ff6f2ea8d5a97bc6b93/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f636f64656e636f2d6465762f656c6f7175656e742d6d6f64656c2d7465737465722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/codenco-dev/eloquent-model-tester)

This package allows you to test your models about table structures, relations and more

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require codenco-dev/eloquent-model-tester --dev
```

Usage
-----

[](#usage)

To use this package, you have to generate factories for your models. ( See [Factories Documentation](https://laravel.com/docs/6.x/database-testing#writing-factories)) You can generate one test file by model or for several. For your model `MyModel` you can use this command for example:

```
php artisan make:model MyModel -mf
php artisan make:test Models/MyModelTest
```

To be able to test database, don't forget `RefreshDatabase` use statements.

```
namespace Tests\Feature\Models;

use App\MyModel;
use CodencoDev\EloquentModelTester\HasModelTester;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class MyModelTest extends TestCase
{
    use RefreshDatabase;
    use HasModelTester;

    public function test_have_my_model_model()
    {
        //...
    }
}

```

For more simplicity, you can put the `RefreshDatabase` use statement in `tests/TestCase.php` file

### Test of structure and of fillable / guarded

[](#test-of-structure-and-of-fillable--guarded)

With this structure

```
users
    id - integer
    name - string
    email - string
    password - string
    remember_token - string
    other_field - string
    created_at - timestamp
    updated_at - timestamp

```

you can test if you have all the fields you need and if they are fillable or guarded.

```
class UserTest extends TestCase
{
    use HasModelTestor;

    public function test_have_user_model()
    {
        $this->modelTestable(User::class)
            ->assertHasColumns(['id','name','email','password','remember_token'])
            ->assertHasColumnsInFillable(['name','password'])
            ->assertHasColumnsInGuarded(['remember_token'])
            ->assertHasTimestampsColumns();
    }
}
```

The function `assertHasColumns()` only checks if the values provided are in the schema of the table. If you want to ensure that no other columns are present, you can use the stricter `assertHasOnlyColumns()` assertion to check that \* only\* the column names provided are present in the table.

***N.B. When using this you will need to provide the `created_at` and `updated_at` fields if they are present in the database table.***

The functions `assertHasColumnsInFillable()` and `assertHasColumnsInGuarded()` only check if the `$fillable`and `$guarded` arrays contain the values passed. If you want to ensure that no other entries are in the `$fillable`and `$guarded` arrays, then you can use the stricter `assertHasOnlyColumnsInFillable()`and `assetHasOnlyColumnsInGuarded()` functions as follows:

```
class UserTest extends TestCase
{
    use HasModelTestor;

    public function test_have_user_model()
    {
        $this->modelTestable(User::class)
            ->assertHasOnlyColumns(['id','name','email','password','remember_token', 'created_at', 'updated_at']) // Will fail as missing 'other_field'.
            ->assertHasOnlyColumnsInFillable(['name','password'])
            ->assertHasOnlyColumnsInGuarded(['remember_token']);
    }
}
```

To further confirm that only a set of columns can be filled, you can use the `assertCanOnlyFill()` assertion to confirm this. This assertion confirms that the fields provided are the only columns that can be filled, by confirming that these are the only values in the `$fillable` array and they don't appear in the `$guarded` array.

```
class User extends Model
{
    $fillable = ['name', 'password', 'email'];

    $guarded = ['remember_token'];
}

class UserTest extends TestCase
{
    use HasModelTestor;

    public function test_have_user_model()
    {
        $this->modelTestable(User::class)
            ->assertHasColumns(['id','name','email','password','remember_token'])
            ->assertCanOnlyFill(['name','password']); // Will fail as 'email' is in the fillable array.
    }
}
```

To confirm that a field does not appear in both the `$fillable` and `$guarded` arrays by mistake there is the `assertNoGuardedAndFillableFields()` assertion that checks that no entry appears in both:

```
class User extends Model
{
    $fillable = ['name', 'password', 'email'];

    $guarded = ['email'];
}

class UserTest extends TestCase
{
    use HasModelTestor;

    public function test_have_user_model()
    {
        $this->modelTestable(User::class)
            ->assertNoGuardedAndFillableFields(); // Will fail as 'email' is in both the fillable & guarded arrays.
    }
}
```

To check for soft delete `deleted_at` column on your model, you can use the `assertHasSoftDeleteTimestampColumns()`assertion:

```
user:
    id - integer
    name - string
    deleted_at - timestamp

```

```
use Illuminate\Database\Eloquent\SoftDeletes;

class User extends Model
{
    use SoftDeletes;
}

class UserTest extends TestCase
{
    use HasModelTestor;

    public function test_have_user_model()
    {
        $this->modelTestable(User::class)
            ->assertHasSoftDeleteTimestampColumns();
    }
}
```

### HasOne et BelongsTo

[](#hasone-et-belongsto)

You can test relations of your models. For example, with this structure

```
user
    id - integer
    name - string

phones
    id - integer
    number - string
    user_id - integer

```

you can use `assertHasHasOneRelation()` and `assertHasBelongsToRelations` methods like this:

```
class UserTest extends TestCase
{
    use HasModelTestor;

    public function test_have_category_model()
    {
        $this->modelTestable(User::class)
            ->assertHasHasOneRelation(Phone::class);
    }

}

class PhoneTest extends TestCase
{
    use HasModelTestor;

    public function test_have_customer_model()
    {
        $this->modelTestable(Phone::class)
            ->assertHasBelongsToRelation(User::class);
    }
}
```

### HasMany et BelongsTo

[](#hasmany-et-belongsto)

You can test relations of your models. For example, with this structure

```
categories
    id - integer
    name - string

customers
    id - integer
    name - string
    category_id - integer
    type_id - integer

```

you can use `assertHasHasManyRelations` and `assertHasBelongsToRelations` methods like this

```
class CategoryTest extends TestCase
{
    use HasModelTestor;

    public function test_have_category_model()
    {
        $this->modelTestable(Category::class)
            ->assertHasHasManyRelation(Customer::class);
    }

}

class CustomerTest extends TestCase
{
    use HasModelTestor;

    public function test_have_customer_model()
    {
        $this->modelTestable(Customer::class)
            ->assertHasBelongsToRelation(Category::class);
    }
}
```

If you don't use Laravel naming convention, you may also override the relation and local keys (for belongsTo relation) by passing additional arguments to the `assertHasHasManyRelations` and `assertHasBelongsToRelations` methods

```
    $this->modelTestable(Customer::class)
            ->assertHasBelongsToRelation(Category::class,'category','category_id');

    $this->modelTestable(Category::class)
            ->assertHasHasManyRelation(Customer::class,'customers');
```

If you have several relations, you can chain methods like this:

```
    $this->modelTestable(Customer::class)
            ->assertHasBelongsToRelation(Category::class)
            ->assertHasBelongsToRelation(OtherModel::class);
```

### HasManyThrough relations

[](#hasmanythrough-relations)

You can test has many through relations of your models. For example, with this structure

```
customers
    id - integer
    name - string

locations
    id - integer
    customer_id - integer

orders
    id - integer
    location_id - integer

```

you can use `assertHasHasManyThroughRelations` method like this

```
class CustomersTest extends TestCase
{
    use HasModelTestor;

    public function test_have_orders_model()
    {
        $this->modelTestable(Customer::class)
            ->assertHasHasManyThroughRelation(Order::class, Location::class);
    }

}
```

If you don't use Laravel naming convention, you may also override the relation and foreign keys by passing additional arguments to the `assertHasHasManyThroughRelations` method

```
    $this->modelTestable(Customer::class)
            ->assertHasHasManyThroughRelation(Order::class, Location::class, 'sales', 'prefix_customer_id', 'prefix_location_id', 'firstPrimaryKey', 'secondPrimaryKey');
```

*Attention*: as there is no **official** inverse of this relationship, it is not possible to use this assertion in the reverse, i.e., in the `orders` model checking for a `customers` relationship.

### Many to Many relations

[](#many-to-many-relations)

You can test your ManyToMany relations with the `ManyToManyRelationsTestable` trait.

```
users
    id - integer
    name - string

roles
    id - integer
    name - string

role_user
    user_id - integer
    role_id - integer

```

```
class UserTest extends TestCase
{
     use HasModelTestor;

    public function test_have_user_model()
    {
        $this->modelTestable(User::class)
            ->assertHasManyToManyRelation(Role::class);
    }

}

class RoleTest extends TestCase
{
    use HasModelTestor;

    public function test_have_role_model()
    {
        $this->modelTestable(User::class)
            ->assertHasManyToManyRelation(User::class);
    }

}
```

You can override the relation argument too :

```
    $this->modelTestable(User::class)
            ->assertHasManyToManyRelation(User::class,'users');
```

### Morph Relations

[](#morph-relations)

If you have a Morph Relation,

```
posts
    id - integer
    title - string
    body - text

videos
    id - integer
    title - string
    url - string

comments
    id - integer
    body - text
    commentable_id - integer
    commentable_type - string

```

you can use `assertHasBelongsToMorphRelations` and `assertHasHasManyMorphRelations` methods like this

```
class PostTest extends TestCase
{

    use HasModelTestor;

    public function test_have_post_model()
        {
            $this->modelTestable(Post::class)
                ->assertHasHasManyMorphRelation(Comment::class,'comments');
        }
}

class VideoTest extends TestCase
{
    use HasModelTestor;

    public function test_have_video_model()
        {
            $this->modelTestable(Video::class)
                ->assertHasHasManyMorphRelation(Comment::class,'comments');
        }
}

class CommentTest extends TestCase
{

    use HasModelTestor;

    public function test_have_morph_model_model()
    {
        $this->modelTestable(Comment::class)
           ->assertHasBelongsToMorphRelation(Post::class,'commentable')
           ->assertHasBelongsToMorphRelation(Video::class,'commentable');
    }
}
```

#### MorphOne Relations

[](#morphone-relations)

If you have a Morph One Relation,

```
posts
    id - integer
    title - string
    body - text

users
    id - integer
    title - string

images
    id - integer
    url - string
    imageable_id - integer
    imageable_type - string

```

you can use `assertHasBelongsToMorphRelations` and `assertHasMorphOneRelations` methods like this

```
class PostTest extends TestCase
{

    use HasModelTestor;

    public function test_have_post_model()
        {
            $this->modelTestable(Post::class)
                ->assertHasMorphOneRelation(Image::class);
        }
}

class UserTest extends TestCase
{
    use HasModelTestor;

    public function test_have_user_model()
        {
            $this->modelTestable(User::class)
                ->assertHasMorphOneRelation(Image::class, 'avatar');
        }
}

class ImageTest extends TestCase
{

    use HasModelTestor;

    public function test_have_image_model()
    {
        $this->modelTestable(Image::class)
           ->assertHasBelongsToMorphRelation(Post::class,'imageable')
           ->assertHasBelongsToMorphRelation(User::class,'imageable');
    }
}
```

### Pivot and table without Model

[](#pivot-and-table-without-model)

You can test if a table contains columns with the `tableTestable` method

```
class MyPivotTest extends TestCase
{
    public function test_have_table_without_model()
    {
        $this->tableTestable('pivot_table')
            ->assertHasColumns(['first_model_id','second_model_id','other_property']);
    }
}
```

### Model Scopes

[](#model-scopes)

You can test if a model has a query scope defined using the `assertHasScope()` assertion:

```
class User extends Model
{
    /**
     * Scope a query to only include popular users.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopePopular($query)
    {
        return $query->where('votes', '>', 100);
    }
}

class UserTest extends TestCase
{
    use HasModelTestor;

    public function test_have_user_model()
    {
        $this->modelTestable(User::class)
            ->assertHasScope('popular');
    }
}
```

Of course if you're using Dynamic Scopes then `assertHasScope()` takes the arguments to pass to the query scope:

```
class User extends Model
{
    /**
    * Scope a query to only include users of a given type.
    *
    * @param  \Illuminate\Database\Eloquent\Builder  $query
    * @param  mixed  $type
    * @return \Illuminate\Database\Eloquent\Builder
    */
    public function scopeOfType($query, $type)
    {
        return $query->where('type', $type);
    }
}

class UserTest extends TestCase
{
    use HasModelTestor;

    public function test_have_user_model()
    {
        $this->modelTestable(User::class)
            ->assertHasScope('ofType', 'admin');
    }
}
```

### Available Assertions

[](#available-assertions)

AssertionDescriptionNotes`assertHasTimestampsColumns()`checks if the `created_at` and `updated_at` columns are present in the table.`assertHasSoftDeleteTimestampColumns()`checks if the `deleted_at` column is present in the table.`assertHasColumns()`checks for the presence of the provided column names appear in the table.`assertHasOnlyColumns()`checks that only the column names provided are the only columns of the table.`assertCanOnlyFill()`checks that only the fields provided can be filled and no others.`assertCanFillables()`checks if the fields provided can be filled.*Deprecated* - Alias of `assertHasColumnsInFillable()``assertHasColumnsInFillable()`checks if the fields provided can be filled.`assertHasOnlyColumnsInFillable()`checks if only the fields provided are those that appear in the $fillable array.`assertHasColumnsInGuarded()`checks if the fields provide are guarded.`assertHasOnlyColumnsInGuarded()`checks if the only the fields provided are those that appear in the $guarded array.`assertHasNoGuardedAndFillableFields()`checks that a column does not appear in both the $fillable and $guarded arrays.`assertHasHasOneRelation()`checks that the model has the `HasOne` relation.`assertHasMorphOneRelation()`checks that the model has the `MorphOne` relation.`assertHasHasManyRelation()`checks that the model hsa the `HasMany` relation.`assertHasHasManyThroughRelation()`checks that the model has the `HasManyThrough` relation.`assertHasBelongsToRelation()`checks that the model has the `BelongsTo` relation.`assertHasManyToManyRelation()`checks that the model has the `ManyToMany` relation.`assertHasHasManyMorphRelation()`checks that the model has the `HasManyMorph` relation.`assertHasBelongsToMorphRelation()`checks that the model has the `BelongsToMorph` relation.`assertHasScope()`checks that the model has the scope.### Testing

[](#testing)

```
composer test
```

### Changelog

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information about what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

### Security

[](#security)

If you discover any security related issues, please email  or contact me on Twitter [DomThomasEs](https://twitter.com/DomThomasEs) instead of using the issue tracker.

Credits
-------

[](#credits)

- [Dominique THOMAS](https://github.com/thomasdominic)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

Laravel Package Boilerplate
---------------------------

[](#laravel-package-boilerplate)

This package was generated using the [Laravel Package Boilerplate](https://laravelpackageboilerplate.com).

###  Health Score

49

—

FairBetter than 95% of packages

Maintenance69

Regular maintenance activity

Popularity32

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity69

Established project with proven stability

 Bus Factor1

Top contributor holds 68.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~126 days

Recently: every ~289 days

Total

17

Last Release

163d ago

Major Versions

v0.9.2 → v1.0.02020-06-01

v1.0.1 → v2.0.02021-07-02

v2.7.1 → v3.0.02024-05-05

v3.0.0 → v4.0.02025-12-07

PHP version history (3 changes)0.9.0PHP ^7.4

v2.0.0PHP ^7.4 || ^8.0

v2.2.0PHP ^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/19ce7305c373d4ab9f6633a2d2ddb3693ae27a1fdd2897244a6e3e4c9760d581?d=identicon)[DomThomas-Dev](/maintainers/DomThomas-Dev)

---

Top Contributors

[![domthomas-dev](https://avatars.githubusercontent.com/u/17202290?v=4)](https://github.com/domthomas-dev "domthomas-dev (98 commits)")[![rabrowne85](https://avatars.githubusercontent.com/u/8293543?v=4)](https://github.com/rabrowne85 "rabrowne85 (46 commits)")

---

Tags

laraveleloquentrelationeloquent-model-testerdomthomas-dev

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/codenco-dev-eloquent-model-tester/health.svg)

```
[![Health](https://phpackages.com/badges/codenco-dev-eloquent-model-tester/health.svg)](https://phpackages.com/packages/codenco-dev-eloquent-model-tester)
```

###  Alternatives

[tucker-eric/eloquentfilter

An Eloquent way to filter Eloquent Models

1.8k4.8M26](/packages/tucker-eric-eloquentfilter)[watson/validating

Eloquent model validating trait.

9723.3M47](/packages/watson-validating)[reedware/laravel-relation-joins

Adds the ability to join on a relationship by name.

2121.2M13](/packages/reedware-laravel-relation-joins)[cybercog/laravel-love

Make Laravel Eloquent models reactable with any type of emotions in a minutes!

1.2k302.7k1](/packages/cybercog-laravel-love)[cviebrock/eloquent-taggable

Easy ability to tag your Eloquent models in Laravel.

567694.8k3](/packages/cviebrock-eloquent-taggable)[highsolutions/eloquent-sequence

A Laravel package for easy creation and management sequence support for Eloquent models with elastic configuration.

121130.3k](/packages/highsolutions-eloquent-sequence)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
