Skip to content
Advertisement

Laravel / PHPUnit: Asserting sameness of two models

When integration testing (using a database) in Laravel. What is the best way to assert that two instances of the same Eloquent model are the same?

AssertEquals $model $model

Simply using ->assertEquals($modelOne, $modelTwo); wont work as even if they are the same PHPUnit checks class properties such as wasRecentlyCreated and sometimes model ids can be a string or an integer.

AssertEquals $model->id $model->id

The problem here is model one may be an instance of another model e.g:

AssertEquals(Person::find(1)->id, Animal::find(1)->id); returns true.

AssertEquals $model->toArray() $model->toArray()

The issue here is properties are not always cast as the same type, Im not 100% sure why but there are times a models properties will be an int and other times a number string

AssertEquals($address->toArray(), $user->address->toArray())

[ postcode => 2454 ]
[ postcode => "2454" ]

How to assert in a simple, clean and repeatable manner two Eloquent models are the same database record?

Advertisement

Answer

One option would be to use PHPUnit’s assertTrue method combined with the is method on the IlluminateDatabaseEloquent class.

$this->assertTrue($modelOne->is($modelTwo));

The is method will return true if the model you pass as an argument is not null, has the same primary key, same table and same connection.

With regards to testing the sameness of attributes, you should be safe just using PHPUnit’s assertEquals on each model’s attributes, which you can retrieve using getAttributes.

$model1 = new Model(['id' => 1, 'name' => 'test', 'enabled' => 0, 'number' => '1']);
$model2 = new Model(['id' => 1, 'name' => 'test', 'enabled' => false, 'number' => 1]);

$this->assertEquals($model1->getAttributes(), $model2->getAttributes());

In my tests, I have found that these assertions pass. The assertEquals method compares values loosely, in that values are compared as using == rather than the strict comparison (or identity) operator, ===. Internally, it will sort both of the arrays provided, and loosely compare values with the same keys. If you have any extra attributes on one model but not the other, the assertion will fail as well.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement