Framework: Is there a way to verify the queue method in Listener works?

Created on 9 Aug 2018  路  7Comments  路  Source: laravel/framework

Laravel Version: 5.5.40
PHP Version: 7.1.20
Queue driver: redis/horizon

I want to conditionally push listeners to queue but even when I add the queue method to my listener, I see the listener added to the queue (in horizon).
Here is my listener code:

<?php

namespace App\Listeners;

use App\Events\PostHasNewComment;
use App\Notifications\YouWereMentioned;
use Illuminate\Contracts\Queue\ShouldQueue;

class NotifyMentionedUsers implements ShouldQueue
{

    public function __construct()
    {
    }

    public function queue($queue, $job, $data)
    {
        $event = unserialize($data['data'])[0];

        if (!$event->mentionedUsers) {
            return false;
        }

        $queue->push($job, $data);
    }

    public function handle(PostHasNewComment $event)
    {
        if ($event->mentionedUsers) { // so this line can be removed if the queue method works!
            $event->mentionedUsers
            ->filter(function ($user) use ($event) {
                return $user->id !== (int)$event->comment->user_id;
            })
            ->each(function ($user) use ($event) {
                $user->notify(new YouWereMentioned($event->comment));
            });
        }
    }
}

Most helpful comment

Add a shouldQueue method, it receives the $event as an argument and should return a boolean.

All 7 comments

Add a shouldQueue method, it receives the $event as an argument and should return a boolean.

@themsaid Thanks! I removed the queue method and added shouldQueue and it works now. I can verify it using horizon. But is it possible to verify it in my test? My Event has multiple Listeners and I can only see the first one with the following test:

/** @test */
public function if_no_one_is_mentioned_then_the_notify_mentioned_users_should_not_be_queued()
{
    Queue::fake();

    $john = factory('App\User')->create(['username' => 'JohnDoe']);

    $post = factory('App\Post')->create();

    $response = $this->actingAs($john)->json('POST',
        route('comments.store', [$post->id]), [
            'body' => 'no one mentioned here'
        ]
    );

    Queue::assertPushed(CallQueuedListener::class, function ($job) {
        // dd($job->class); this only has the first listener which is NotifyBlogOwner
        return $job->class == NotifyMentionedUsers::class;
    });
}

does Queue::assertPushed(CallQueuedListener::class, function ($job){}); iterates through the jobs? because the test passes but if I do the dd() I can only see the first listener.

If shouldQueue returned false the listener won't be queued at all, not sure if I understand your concern :)

@themsaid I mean how can I test it. Given I have a comment that has mentioned users I want to assert that the listener for notifyingMentiinedUsers gets added to the queue. And also the opposite to assert the listener not sent to queue if no one mentioned.

I have tested everything but just need to assert that the listener did not go to queue and the opposite when the listener does go to queue I want to assert that in my tests

https://laravel.com/docs/5.5/mocking#queue-fake might be what your looking for.

@rs-sliske @themsaid I did a Log and found that the Queue::assertPushed(CallQueuedListener::class, function ($job) {} does iterate through the jobs so I have to do that 2 times one to check if it has a job and the other time if it does not have the other one

Queue::assertPushed(CallQueuedListener::class, function ($job) {
        return $job->class == ListenerThatShouldQueue::class;
});

Queue::assertNotPushed(CallQueuedListener::class, function ($job) {
        return $job->class == ListenerThatShouldNotQueue::class;
});

Thanks @themsaid for the help :+1:

Was this page helpful?
0 / 5 - 0 ratings