Testing Model Observer Events - Laravel 5.6

Posted 3 months ago by clemblanco

I'm facing a weird issue today while trying to test a Model Observer Event.

App\Providers\AppServiceProvider

public function boot()
{
    User::observe(UserObserver::class);
}

App\Observers\UserObserver

public function created(User $user)
{
    event(new FooEvent);
}

App\Providers\EventServiceProvider

protected $listen = [
    'App\Events\FooEvent' => ['App\Listeners\BarListener']
];

App\Listeners\BarListener

class BarListener implements ShouldQueue
{
    public function handle(FooEvent $event)
    {
        // Something happens here...
    }
}

Now in my test if I do:

Queue::fake();

factory(User::class)->create();

Queue::assertPushed(BarListener::class)

The assertion will always fail saying The expected [App\Listeners\BarListener] job was not pushed.

Now if I dig a bit deeper in what this assertPushed() does, I can find that it runs through:

Illuminate\Support\Testing\Fakes\QueueFake

public function hasPushed($job)
{
    return isset($this->jobs[$job]) && ! empty($this->jobs[$job]);
}

and if I dump $this->jobs I can see it coming as:

array:1 [
  "Illuminate\Events\CallQueuedListener" => array:1 [
    0 => array:2 [
      "job" => Illuminate\Events\CallQueuedListener {#2709
        +class: "App\Listeners\BarListener"
        +method: "handle"
        +data: array:1 [
          0 => App\Events\FooEvent {#2715
            +user: App\User {#2832
              ...
            }
          ]
        }
      ]
    }
  ]
]

I understand that instead of having Illuminate\Events\CallQueuedListener I should see App\Listeners\BarListener used as a key in that array but I'm not entirely sure why...

Does it come from the fact I'm using a Model Observer to trigger another Event?

Or should Queue::assertPushed() only be used with Jobs? Not Listeners?

Or is it completely normal and should I instead assert that CallQueuedListener is triggered with the associated arguments with the following?

Queue::fake();

factory(User:class)->create();

Queue:: assertPushed(\Illuminate\Events\CallQueuedListener::class, function ($job) {
    return $job->class === \App\Listeners\BarListener::class;
});

I'm a bit confused...

Please sign in or create an account to participate in this conversation.

Reply to

Use Markdown with GitHub-flavored code blocks.