Test Queue functionality?

I'll-Be-Back picture I'll-Be-Back · Sep 30, 2017 · Viewed 7k times · Source

According to the Laravel Documentation, I can use Queue::fake(); prevent jobs from being queued.

What is not clear how to test (PHPUnit) a few methods in the Job Class while it is not being queued.

For example:

class ActionJob extends Job
{
    public $tries = 3;
    protected $data;

    public function __construct($data)
    {
        $this->data = $data;
    }


    public function handle()
    {
        if ($this->data['action'] == "deleteAllFiles") {
            $this->deleteAllFiles();
        }
    }

    protected function deleteAllFiles()
    {
        //delete all the files then return true
        // if failed to delete return false
    }
}

Here is example I want to test deleteAllFiles() - do I need to mock it?

Answer

tptcat picture tptcat · Sep 30, 2017

The idea of using the fakes is that they're an alternative to mocking. So, yes, if you want to mock that deleteAllFiles() was called, then I don't believe you can do that with the fake.

However, you can assert that a certain attribute exists on the job.

One thing, it's not in your example, but make sure your job is implementing \Illuminate\Contracts\Queue\ShouldQueue.

Something like this

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class ActionJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $tries = 3;

    public $data; // Make sure this public so you can access it in your test

    public function __construct($data)
    {
        $this->data = $data;
    }


    public function handle()
    {
        if ($this->data['action'] == "deleteAllFiles") {
            $this->deleteAllFiles();
        }
    }

    protected function deleteAllFiles()
    {
        // do stuff
    }
}

Then in your test:

// ActionJobTest.php
Queue::fake();

// Do some things to set up date, call an endpoint, etc.

Queue::assertPushed(ActionJob::class, function ($job) {
    return $job->data['action'] === 'deleteAllFiles';
});

If you want to assert on $data within the job, then you can make some other state change and assert on that in the Closure.

Side note: If the Job is Disptachable you can also assert like this:

// ActionJobTest.php
Bus::fake();

// Do some things to set up date, call an endpoint, etc.

Bus::assertDispatched(ActionJob::class, function ($job) {
    return $job->data['action'] === 'deleteAllFiles';
});