Recently I had to create a model factory for my tests but I didn't want it to fire the standard Laravel model events.
Model events are fired whenever a record is created, updated, deleted and retrieved.
You can learn more about model events on the Laravel documentation.
Normally to remove the model events you can use the flushEventListeners
method on the HasEvents
trait.
/**
* Remove all of the event listeners for the model.
*
* @return void
*/
public static function flushEventListeners()
{
if (! isset(static::$dispatcher)) {
return;
}
$instance = new static;
foreach ($instance->getObservableEvents() as $event) {
static::$dispatcher->forget("eloquent.{$event}: ".static::class);
}
foreach (array_values($instance->dispatchesEvents) as $event) {
static::$dispatcher->forget($event);
}
}
When using Laravel factories they go through the FactoryBuilder
class, which has the Macroable
trait.
This means we can easily extend this class to do what we want it to do.
In your factory classes you can use the following code.
<?php
use \Illuminate\Database\Eloquent\FactoryBuilder;
FactoryBuilder::macro('disableEvents', function () {
$this->class::flushEventListeners();
return $this;
});
Now in your tests when building your factory you can use the disableEvents
method.
<?php
factory(User::class)->disableEvents()->create();