TheNiceGuy
TheNiceGuy

Reputation: 3730

Laravel Event Mocking

I have a test with this code

Event::fake();

Queue::fake();

// Fake an order
$order = factory(Order::class)->make();

event(new PaymentWasCompleted($order));

Event::assertDispatched(PaymentWasCompleted::class, function ($e) use ($order) {
    return $e->order->id === $order->id;
});

Queue::assertPushed(GenerateInvoiceJob::class, function ($job) use ($order) {
    return $job->order->id === $order->id;
});

My EventServiceProvider looks like this:

   protected $listen = [
        \App\Events\PaymentWasCompleted::class => [
            \App\Listeners\GenerateInvoice::class,
        ]
    ];

And the GenerateInvoice listener looks like this:

   public function __construct()
    {
        $this->eventName = 'GenerateInvoice';
    }

 public function handle(PaymentWasCompleted $event)
    {
        // Access the order using $event->order
        $order = $event->order;

        $job = (new GenerateInvoiceJob($order, $this))->onQueue(app('QueueHelper')->getQueueName($this->eventName));
        $this->dispatch($job);
    }

I would expect the test to be passing, but it fails with:

The expected [App\Jobs\GenerateInvoiceJob] job was not pushed.

I am unsure why that is.

I also tried

Queue::assertPushedOn(app('QueueHelper')->getQueueName('GenerateInvoice'), GenerateInvoiceJob::class, function ($job) use ($order) {
            return $job->order->id === $order->id;
        });

same issue.

Upvotes: 4

Views: 5599

Answers (1)

TheNiceGuy
TheNiceGuy

Reputation: 3730

After re-reading the docs, it is clear that this is intended behaviour. The docs say

As an alternative to mocking, you may use the Event facade's fake method to prevent all event listeners from executing.

As described in a comment, I have to create two tests. One for making sure that the event has been fired and contains the expected data and a second one for making sure that the event listeners get fired.

So, first Test:

Event::fake();

$order = factory(Order::class)->make();

event(new PaymentWasCompleted($order));

Event::assertDispatched(PaymentWasCompleted::class, function ($e) use ($order) {
    return $e->order->id === $order->id;
});

Second test:

Queue::fake();

$order = factory(Order::class)->make();

event(new PaymentWasCompleted($order));

Queue::assertPushed(GenerateInvoiceJob::class, function ($job) use ($order) {
    return $job->order->id === $order->id;
});

As expected, this tests pass.

Upvotes: 11

Related Questions