Laravel 4 model events do not work with PHPUnit

I will build model validation in Laravel 4 with creating Model Event:

 class User extends Eloquent { public function isValid() { return Validator::make($this->toArray(), array('name' => 'required'))->passes(); } public static function boot() { parent::boot(); static::creating(function($user) { echo "Hello"; if (!$user->isValid()) return false; }); } } 

It works well, but I have problems with PHPUnit. The following two tests are exactly the same, but only the first pass:

 class UserTest extends TestCase { public function testSaveUserWithoutName() { $count = User::all()->count(); $user = new User; $saving = $user->save(); assertFalse($saving); // pass assertEquals($count, User::all()->count()); // pass } public function testSaveUserWithoutNameBis() { $count = User::all()->count(); $user = new User; $saving = $user->save(); assertFalse($saving); // fail assertEquals($count, User::all()->count()); // fail, the user is created } } 

If I try to create a user twice in the same test, it will work, but this is similar if the binding event is present only in the first test of my test class. echo "Hello"; printed only once during the first test run.

I am simplifying the matter for my question, but you can see the problem: I cannot verify several validation rules in different unit tests. I have been trying almost everything since then, but I have almost jumped out of the windows! Any idea?

+7
phpunit laravel laravel-4
source share
2 answers

The issue is well documented on Github. See Comments above that explain this further.

I modified one of the β€œsolutions” in Github to automatically reset all model events during the tests. Add the following to the TestCase.php file.

application / tests / TestCase.php

 public function setUp() { parent::setUp(); $this->resetEvents(); } private function resetEvents() { // Get all models in the Model directory $pathToModels = '/app/models'; // <- Change this to your model directory $files = File::files($pathToModels); // Remove the directory name and the .php from the filename $files = str_replace($pathToModels.'/', '', $files); $files = str_replace('.php', '', $files); // Remove "BaseModel" as we dont want to boot that moodel if(($key = array_search('BaseModel', $files)) !== false) { unset($files[$key]); } // Reset each model event listeners. foreach ($files as $model) { // Flush any existing listeners. call_user_func(array($model, 'flushEventListeners')); // Reregister them. call_user_func(array($model, 'boot')); } } 
+3
source share

I have my models in subdirectories, so I changed @TheShiftExchange code a bit

 //Get all models in the Model directory $pathToModels = '/path/to/app/models'; $files = File::allFiles($pathToModels); foreach ($files as $file) { $fileName = $file->getFileName(); if (!ends_with($fileName, 'Search.php') && !starts_with($fileName, 'Base')) { $model = str_replace('.php', '', $fileName); // Flush any existing listeners. call_user_func(array($model, 'flushEventListeners')); // Re-register them. call_user_func(array($model, 'boot')); } } 
0
source share

All Articles