Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 562
AndrewMcLagan Avatar asked Mar 21 '18 21:03

AndrewMcLagan


1 Answers

One option would be to use PHPUnit's assertTrue method combined with the is method on the Illuminate\Database\Eloquent 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.

like image 116
Jonathon Avatar answered Oct 17 '22 22:10

Jonathon