1. Profundizando
  2. Eventos

Introducción

Los eventos de Laravel proporcionan una implementación simple del patrón de observador, lo que le permite suscribirse y escuchar varios eventos que ocurren dentro de su aplicación. Las clases de eventos se almacenan típicamente en el directorio app/Events, mientras que sus escuchadores se almacenan en app/Listeners. No se preocupe si no ve estos directorios en su aplicación, ya que se crearán automáticamente a medida que genere eventos y escuchadores utilizando los comandos de consola de Artisan.

Los eventos son una excelente manera de desacoplar varios aspectos de su aplicación, ya que un solo evento puede tener múltiples escuchadores que no dependen entre sí. Por ejemplo, puede desear enviar una notificación de Slack a su usuario cada vez que se envía un pedido. En lugar de acoplar su código de procesamiento de pedidos con su código de notificación de Slack, puede generar un evento App\Events\OrderShipped que un escuchador puede recibir y usar para despachar una notificación de Slack.

Registrar Eventos y Oyentes

El App\Providers\EventServiceProvider incluido con tu aplicación Laravel proporciona un lugar conveniente para registrar todos los escuchadores de eventos de tu aplicación. La propiedad listen contiene una matriz de todos los eventos (claves) y sus escuchadores (valores). Puedes agregar tantos eventos a esta matriz como tu aplicación necesite. Por ejemplo, agreguemos un evento OrderShipped:

use App\Events\OrderShipped;
use App\Listeners\SendShipmentNotification;
 
/**
* Los mapeos de los oyentes de eventos para la aplicación.
*
* @var array<class-string, array<int, class-string>>
*/
protected $listen = [
OrderShipped::class => [
SendShipmentNotification::class,
],
];

Nota Puede utilizar el comando event:list para mostrar una lista de todos los eventos y escuchadores registrados por su aplicación.

Generar Eventos y Oyentes

Por supuesto, crear manualmente los archivos para cada evento y escuchador es engorroso. En su lugar, agrega escuchadores y eventos a tu EventServiceProvider y utiliza el comando Artisan event:generate. Este comando generará cualquier evento o escuchador que esté listado en tu EventServiceProvider y que aún no exista:

php artisan event:generate

Alternativamente, puedes utilizar los comandos Artisan make:event y make:listener para generar eventos y escuchadores individuales:

php artisan make:event PodcastProcessed
 
php artisan make:listener SendPodcastNotification --event=PodcastProcessed

Registrar Eventos Manualmente

Normalmente, los eventos deberían registrarse mediante la matriz $listen de EventServiceProvider; sin embargo, también puedes registrar escuchadores de eventos basados en clases o cierres manualmente en el método boot de tu EventServiceProvider:

use App\Events\PodcastProcessed;
use App\Listeners\SendPodcastNotification;
use Illuminate\Support\Facades\Event;
 
/**
* Registra cualquier otro evento para tu aplicación.
*/
public function boot(): void
{
Event::listen(
PodcastProcessed::class,
SendPodcastNotification::class,
);
 
Event::listen(function (PodcastProcessed $event) {
// ...
});
}

Oyentes de Eventos Anónimos en Cola

Cuando registras manualmente escuchadores de eventos basados en cierres, puedes envolver el cierre del escuchador dentro de la función Illuminate\Events\queueable para indicar a Laravel que ejecute el escuchador utilizando la cola:

use App\Events\PodcastProcessed;
use function Illuminate\Events\queueable;
use Illuminate\Support\Facades\Event;
 
/**
* Registra cualquier otro evento para tu aplicación.
*/
public function boot(): void
{
Event::listen(queueable(function (PodcastProcessed $event) {
// ...
}));
}

Al igual que con los trabajos en cola, puede utilizar los métodos onConnection, onQueue y delay para personalizar la ejecución del escuchador en cola:

Event::listen(queueable(function (PodcastProcessed $event) {
// ...
})->onConnection('redis')->onQueue('podcasts')->delay(now()->addSeconds(10)));

Si desea manejar fallas de escuchadores en cola anónimos, puede proporcionar un cierre al método catch al definir el escuchador queueable. Este cierre recibirá la instancia del evento y la instancia de Throwable que causó la falla del escuchador:

use App\Events\PodcastProcessed;
use function Illuminate\Events\queueable;
use Illuminate\Support\Facades\Event;
use Throwable;
 
Event::listen(queueable(function (PodcastProcessed $event) {
// ...
})->catch(function (PodcastProcessed $event, Throwable $e) {
// Falló el oyente en cola...
}));

Oyentes de Eventos comodín

Incluso puede registrar escuchadores utilizando * como un parámetro comodín, lo que le permite capturar varios eventos en el mismo escuchador. Los escuchadores comodín reciben el nombre del evento como su primer argumento y todo el array de datos del evento como su segundo argumento:

Event::listen('event.*', function (string $eventName, array $data) {
// ...
});

Descubrimiento de Eventos

En lugar de registrar eventos y escuchadores manualmente en la matriz $listen de EventServiceProvider, puede habilitar el descubrimiento automático de eventos. Cuando el descubrimiento de eventos está habilitado, Laravel encontrará y registrará automáticamente sus eventos y escuchadores escaneando el directorio Listeners de su aplicación. Además, cualquier evento explícitamente definido en EventServiceProvider seguirá siendo registrado.

Laravel encuentra los escuchadores de eventos escaneando las clases de escuchadores utilizando los servicios de reflexión de PHP. Cuando Laravel encuentra cualquier método de clase de escuchador que comienza con handle o __invoke, registrará esos métodos como escuchadores de eventos para el evento que se type-hintea en la firma del método:

use App\Events\PodcastProcessed;
 
class SendPodcastNotification
{
/**
* Maneja el evento dado.
*/
public function handle(PodcastProcessed $event): void
{
// ...
}
}

El descubrimiento de eventos está desactivado de forma predeterminada, pero puede habilitarlo anulando el método shouldDiscoverEvents en EventServiceProvider de su aplicación:

/**
* Determina si los eventos y oyentes deben descubrirse automáticamente.
*/
public function shouldDiscoverEvents(): bool
{
return true;
}

De forma predeterminada, se escanearán todos los escuchadores dentro del directorio app/Listeners de su aplicación. Si desea definir directorios adicionales para escanear, puede anular el método discoverEventsWithin en su EventServiceProvider:

/**
* Obtiene los directorios de oyentes que deben usarse para descubrir eventos.
*
* @return array<int, string>
*/
protected function discoverEventsWithin(): array
{
return [
$this->app->path('Listeners'),
];
}

Descubrimiento de Eventos en Producción

En producción, no es eficiente que el marco escanee todos sus escuchadores en cada solicitud. Por lo tanto, durante su proceso de implementación, debe ejecutar el comando Artisan event:cache para almacenar en caché un manifiesto de todos los eventos y escuchadores de su aplicación. Este manifiesto será utilizado por el marco para acelerar el proceso de registro de eventos. El comando event:clear se puede utilizar para destruir la caché.

Definir Eventos

Una clase de evento es esencialmente un contenedor de datos que contiene la información relacionada con el evento. Por ejemplo, supongamos que un evento App\Events\OrderShipped recibe un objeto Eloquent ORM:

<?php
 
namespace App\Events;
 
use App\Models\Order;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
 
class OrderShipped
{
use Dispatchable, InteractsWithSockets, SerializesModels;
 
/**
* Crea una nueva instancia de evento.
*/
public function __construct(
public Order $order,
) {}
}

Como puede ver, esta clase de evento no contiene lógica. Es un contenedor para la instancia de App\Models\Order que se compró. El rasgo SerializesModels utilizado por el evento serializará graciosamente cualquier modelo Eloquent si el objeto de evento se serializa utilizando la función serialize de PHP, como cuando se utilizan escuchadores en cola.

Definir Oyentes

A continuación, echemos un vistazo al escuchador para nuestro evento de ejemplo. Los escuchadores de eventos reciben instancias de eventos en su método handle. Los comandos Artisan event:generate y make:listener importarán automáticamente la clase de evento adecuada y harán type-hint al evento en el método handle. Dentro del método handle, puede realizar cualquier acción necesaria para responder al evento:

<?php
 
namespace App\Listeners;
 
use App\Events\OrderShipped;
 
class SendShipmentNotification
{
/**
* Crea el oyente de eventos.
*/
public function __construct()
{
// ...
}
 
/**
* Maneja el evento.
*/
public function handle(OrderShipped $event): void
{
// Accede al pedido usando $event->order...
}
}

Nota Tus escuchadores de eventos también pueden hacer uso de la inyección de dependencias en sus constructores. Todos los escuchadores de eventos se resuelven a través del contenedor de servicios de Laravel, por lo que las dependencias se inyectarán automáticamente.

Detener la Propagación de un Evento

A veces, es posible que desee detener la propagación de un evento a otros escuchadores. Puede hacerlo devolviendo false desde el método handle de su escuchador.

Oyentes de Eventos en Cola

La colocación de escuchadores en cola puede ser beneficiosa si su escuchador va a realizar una tarea lenta, como enviar un correo electrónico o realizar una solicitud HTTP. Antes de usar escuchadores en cola, asegúrese de configurar su cola y comenzar un trabajador de cola en su servidor o entorno de desarrollo local.

Para especificar que un escuchador debe estar en cola, agregue la interfaz ShouldQueue a la clase del escuchador. Los escuchadores generados por los comandos Artisan event:generate y make:listener ya tienen esta interfaz importada en el espacio de nombres actual, por lo que puede usarla de inmediato:

<?php
 
namespace App\Listeners;
 
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
 
class SendShipmentNotification implements ShouldQueue
{
// ...
}

¡Eso es todo! Ahora, cuando se despache un evento manejado por este escuchador, el escuchador se colocará automáticamente en cola mediante el despachador de eventos utilizando el sistema de colas de Laravel. Si no se lanzan excepciones cuando el escuchador se ejecuta en la cola, el trabajo en cola se eliminará automáticamente después de que haya terminado de procesarse.

Personalizar la Conexión, Nombre y Retraso de la Cola

Si desea personalizar la conexión de cola, el nombre de la cola o el tiempo de demora de un escuchador de eventos, puede definir las propiedades $connection, $queue o $delay en la clase de su escuchador:

<?php
 
namespace App\Listeners;
 
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
 
class SendShipmentNotification implements ShouldQueue
{
/**
* El nombre de la conexión a la que se debe enviar el trabajo.
*
* @var string|null
*/
public $connection = 'sqs';
 
/**
* El nombre de la cola a la que se debe enviar el trabajo.
*
* @var string|null
*/
public $queue = 'listeners';
 
/**
* El tiempo (segundos) antes de que se deba procesar el trabajo.
*
* @var int
*/
public $delay = 60;
}

Si desea definir la conexión de la cola, el nombre de la cola o la demora de un escuchador en tiempo de ejecución, puede definir los métodos viaConnection, viaQueue o withDelay en el escuchador:

/**
* Obtiene el nombre de la conexión de la cola del oyente.
*/
public function viaConnection(): string
{
return 'sqs';
}
 
/**
* Obtiene el nombre de la cola del oyente.
*/
public function viaQueue(): string
{
return 'listeners';
}
 
/**
* Obtiene el número de segundos antes de que se deba procesar el trabajo.
*/
public function withDelay(OrderShipped $event): int
{
return $event->highPriority ? 0 : 60;
}

Colocar en Cola Oyentes Condicionalmente

A veces, es posible que necesites determinar si un escuchador debe estar en cola según algunos datos que solo están disponibles en tiempo de ejecución. Para lograr esto, se puede agregar un método shouldQueue a un escuchador para determinar si el escuchador debe estar en cola. Si el método shouldQueue devuelve false, el escuchador no se ejecutará:

<?php
 
namespace App\Listeners;
 
use App\Events\OrderCreated;
use Illuminate\Contracts\Queue\ShouldQueue;
 
class RewardGiftCard implements ShouldQueue
{
/**
* Recompensa una tarjeta de regalo al cliente.
*/
public function handle(OrderCreated $event): void
{
// ...
}
 
/**
* Determina si el oyente debe ponerse en cola.
*/
public function shouldQueue(OrderCreated $event): bool
{
return $event->order->subtotal >= 5000;
}
}

Interactuar Manualmente con la Cola

Si necesitas acceder manualmente a los métodos delete y release del trabajo en cola subyacente del escuchador, puedes hacerlo utilizando el rasgo Illuminate\Queue\InteractsWithQueue. Este rasgo se importa por defecto en los escuchadores generados y proporciona acceso a estos métodos:

<?php
 
namespace App\Listeners;
 
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
 
class SendShipmentNotification implements ShouldQueue
{
use InteractsWithQueue;
 
/**
* Maneja el evento.
*/
public function handle(OrderShipped $event): void
{
if (true) {
$this->release(30);
}
}
}

Oyentes de Eventos en Cola y Transacciones de Base de Datos

Cuando los escuchadores en cola se despachan dentro de transacciones de base de datos, pueden procesarse por la cola antes de que la transacción de base de datos se haya confirmado. Cuando esto sucede, cualquier actualización que hayas realizado a modelos o registros de base de datos durante la transacción de base de datos puede no reflejarse aún en la base de datos. Además, cualquier modelo o registro de base de datos creado dentro de la transacción puede no existir en la base de datos. Si tu escuchador depende de estos modelos, pueden ocurrir errores inesperados cuando se procesa el trabajo que despacha el escuchador en cola.

Si la opción de configuración after_commit de tu conexión de cola está configurada como false, aún puedes indicar que un escuchador en cola en particular debe despacharse después de que se hayan confirmado todas las transacciones de base de datos abiertas implementando la interfaz ShouldHandleEventsAfterCommit en la clase del escuchador:

<?php
 
namespace App\Listeners;
 
use Illuminate\Contracts\Events\ShouldHandleEventsAfterCommit;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
 
class SendShipmentNotification implements ShouldQueue, ShouldHandleEventsAfterCommit
{
use InteractsWithQueue;
}

Nota Para obtener más información sobre cómo solucionar estos problemas, consulte la documentación sobre trabajos en cola y transacciones de base de datos.

Manejo de Trabajos Fallidos

A veces, es posible que fallen tus escuchadores de eventos en cola. Si el escuchador en cola excede el número máximo de intentos definido por tu trabajador de cola, se llamará al método failed en tu escuchador. El método failed recibe la instancia del evento y el Throwable que causó la falla:

<?php
 
namespace App\Listeners;
 
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Throwable;
 
class SendShipmentNotification implements ShouldQueue
{
use InteractsWithQueue;
 
/**
* Maneja el evento.
*/
public function handle(OrderShipped $event): void
{
// ...
}
 
/**
* Maneja un fallo de trabajo.
*/
public function failed(OrderShipped $event, Throwable $exception): void
{
// ...
}
}

Especificar el Número Máximo de Intentos del Oyente en Cola

Si uno de tus escuchadores en cola encuentra un error, es probable que no desees que siga intentando indefinidamente. Por lo tanto, Laravel proporciona varias formas de especificar cuántas veces o durante cuánto tiempo se puede intentar un escuchador.

Puedes definir una propiedad $tries en la clase de tu escuchador para especificar cuántas veces se puede intentar el escuchador antes de considerarse que ha fallado:

<?php
 
namespace App\Listeners;
 
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
 
class SendShipmentNotification implements ShouldQueue
{
use InteractsWithQueue;
 
/**
* El número de veces que se puede intentar el oyente en cola.
*
* @var int
*/
public $tries = 5;
}

Como alternativa a definir cuántas veces se puede intentar un escuchador antes de que falle, puedes definir un momento en el que el escuchador ya no debería intentarse. Esto permite que un escuchador se intente cualquier número de veces dentro de un marco de tiempo dado. Para definir el momento en que un escuchador ya no debería intentarse, agrega un método retryUntil a la clase de tu escuchador. Este método debe devolver una instancia de DateTime:

use DateTime;
 
/**
* Determina la hora a la que debería vencer el oyente.
*/
public function retryUntil(): DateTime
{
return now()->addMinutes(5);
}

Despachar Eventos

Para despachar un evento, puedes llamar al método estático dispatch en el evento. Este método está disponible en el evento gracias al rasgo Illuminate\Foundation\Events\Dispatchable. Cualquier argumento pasado al método dispatch se pasará al constructor del evento:

<?php
 
namespace App\Http\Controllers;
 
use App\Events\OrderShipped;
use App\Http\Controllers\Controller;
use App\Models\Order;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
 
class OrderShipmentController extends Controller
{
/**
* Envía el pedido dado.
*/
public function store(Request $request): RedirectResponse
{
$order = Order::findOrFail($request->order_id);
 
// Lógica de envío de pedido...
 
OrderShipped::dispatch($order);
 
return redirect('/orders');
}
}

Si deseas despachar un evento condicionalmente, puedes utilizar los métodos dispatchIf y dispatchUnless:

OrderShipped::dispatchIf($condition, $order);
 
OrderShipped::dispatchUnless($condition, $order);

Nota Al realizar pruebas, puede ser útil afirmar que ciertos eventos se han despachado sin activar realmente sus escuchadores. Las herramientas de prueba integradas de Laravel facilitan esto.

Despachar Eventos Después de Transacciones de Base de Datos

A veces, es posible que desees indicarle a Laravel que solo despache un evento después de que se haya confirmado la transacción de base de datos activa. Para hacerlo, puedes implementar la interfaz ShouldDispatchAfterCommit en la clase del evento.

Esta interfaz instruye a Laravel a no despachar el evento hasta que se haya confirmado la transacción de base de datos actual. Si la transacción falla, el evento se descartará. Si no hay ninguna transacción de base de datos en curso cuando se despacha el evento, el evento se despachará inmediatamente:

<?php
 
namespace App\Events;
 
use App\Models\Order;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
 
class OrderShipped implements ShouldDispatchAfterCommit
{
use Dispatchable, InteractsWithSockets, SerializesModels;
 
/**
* Crea una nueva instancia de evento.
*/
public function __construct(
public Order $order,
) {}
}

Suscriptores de Eventos

Escribir Suscriptores de Eventos

Los suscriptores de eventos son clases que pueden suscribirse a varios eventos desde dentro de la clase del suscriptor en sí, lo que te permite definir varios manejadores de eventos dentro de una sola clase. Los suscriptores deben definir un método subscribe, al cual se le pasará una instancia del despachador de eventos. Puedes llamar al método listen en el despachador dado para registrar escuchadores de eventos:

<?php
 
namespace App\Listeners;
 
use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Logout;
use Illuminate\Events\Dispatcher;
 
class UserEventSubscriber
{
/**
* Maneja eventos de inicio de sesión de usuario.
*/
public function handleUserLogin(Login $event): void {}
 
/**
* Maneja eventos de cierre de sesión de usuario.
*/
public function handleUserLogout(Logout $event): void {}
 
/**
* Registra los oyentes para el suscriptor.
*/
public function subscribe(Dispatcher $events): void
{
$events->listen(
Login::class,
[UserEventSubscriber::class, 'handleUserLogin']
);
 
$events->listen(
Logout::class,
[UserEventSubscriber::class, 'handleUserLogout']
);
}
}

Si los métodos de tus escuchadores de eventos están definidos dentro del propio suscriptor, puede resultarte más conveniente devolver un array de eventos y nombres de métodos desde el método subscribe del suscriptor. Laravel determinará automáticamente el nombre de la clase del suscriptor al registrar los escuchadores de eventos:

<?php
 
namespace App\Listeners;
 
use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Logout;
use Illuminate\Events\Dispatcher;
 
class UserEventSubscriber
{
/**
* Maneja eventos de inicio de sesión de usuario.
*/
public function handleUserLogin(Login $event): void {}
 
/**
* Maneja eventos de cierre de sesión de usuario.
*/
public function handleUserLogout(Logout $event): void {}
 
/**
* Registra los oyentes para el suscriptor.
*
* @return array<string, string>
*/
public function subscribe(Dispatcher $events): array
{
return [
Login::class => 'handleUserLogin',
Logout::class => 'handleUserLogout',
];
}
}

Registrar Suscriptores de Eventos

Después de escribir el suscriptor, estás listo para registrarlo con el despachador de eventos. Puedes registrar suscriptores utilizando la propiedad $subscribe en EventServiceProvider. Por ejemplo, agreguemos UserEventSubscriber a la lista:

<?php
 
namespace App\Providers;
 
use App\Listeners\UserEventSubscriber;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
 
class EventServiceProvider extends ServiceProvider
{
/**
* Los mapeos de los oyentes de eventos para la aplicación.
*
* @var array
*/
protected $listen = [
// ...
];
 
/**
* Las clases de suscriptores para registrar.
*
* @var array
*/
protected $subscribe = [
UserEventSubscriber::class,
];
}

Pruebas

Al probar código que despacha eventos, es posible que desees indicar a Laravel que no ejecute realmente los escuchadores del evento, ya que el código del escuchador se puede probar directa y separadamente del código que despacha el evento correspondiente. Por supuesto, para probar el propio escuchador, puedes instanciar una instancia del escuchador e invocar el método handle directamente en tu prueba.

Usando el método fake de la fachada Event, puedes evitar que los escuchadores se ejecuten, ejecutar el código en prueba y luego afirmar qué eventos despachó tu aplicación mediante los métodos assertDispatched, assertNotDispatched y assertNothingDispatched:

<?php
 
namespace Tests\Feature;
 
use App\Events\OrderFailedToShip;
use App\Events\OrderShipped;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
 
class ExampleTest extends TestCase
{
/**
* Prueba de envío de pedidos.
*/
public function test_orders_can_be_shipped(): void
{
Event::fake();
 
// Realiza el envío de pedidos...
 
// Asegura que se haya despachado un evento...
Event::assertDispatched(OrderShipped::class);
 
// Asegura que se haya despachado un evento dos veces...
Event::assertDispatched(OrderShipped::class, 2);
 
// Asegura que no se haya despachado un evento...
Event::assertNotDispatched(OrderFailedToShip::class);
 
// Asegura que no se haya despachado ningún evento...
Event::assertNothingDispatched();
}
}

Puedes pasar un cierre a los métodos assertDispatched o assertNotDispatched para afirmar que se despachó un evento que pasa una determinada "prueba de verdad". Si se despachó al menos un evento que pasa la prueba de verdad dada, la afirmación será exitosa:

Event::assertDispatched(function (OrderShipped $event) use ($order) {
return $event->order->id === $order->id;
});

Si simplemente deseas afirmar que un escuchador de eventos está escuchando un evento dado, puedes usar el método assertListening:

Event::assertListening(
OrderShipped::class,
SendShipmentNotification::class
);

Advertencia Después de llamar a Event::fake(), ningún escuchador de eventos se ejecutará. Por lo tanto, si tus pruebas utilizan fábricas de modelos que dependen de eventos, como crear un UUID durante el evento creating de un modelo, debes llamar a Event::fake() después de usar tus fábricas.

Falsificación de un Subconjunto de Eventos

Si solo quieres simular escuchadores de eventos para un conjunto específico de eventos, puedes pasarlos al método fake o fakeFor:

/**
* Prueba de proceso de pedido.
*/
public function test_orders_can_be_processed(): void
{
Event::fake([
OrderCreated::class,
]);
 
$order = Order::factory()->create();
 
Event::assertDispatched(OrderCreated::class);
 
// Otros eventos se despachan como de costumbre...
$order->update([...]);
}

Puedes simular todos los eventos excepto un conjunto de eventos especificados usando el método except:

Event::fake()->except([
OrderCreated::class,
]);

Falsificaciones de Eventos con Ámbito

Si solo deseas simular escuchadores de eventos para una parte de tu prueba, puedes usar el método fakeFor:

<?php
 
namespace Tests\Feature;
 
use App\Events\OrderCreated;
use App\Models\Order;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
 
class ExampleTest extends TestCase
{
/**
* Prueba de proceso de pedido.
*/
public function test_orders_can_be_processed(): void
{
$order = Event::fakeFor(function () {
$order = Order::factory()->create();
 
Event::assertDispatched(OrderCreated::class);
 
return $order;
});
 
// Los eventos se despachan como de costumbre y los observadores se ejecutarán...
$order->update([...]);
}
}