Test Queue functionality?
Asked Answered
M

1

7

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?

Mortification answered 30/9, 2017 at 13:54 Comment(4)
Have you tried to pre var_dump following with die;? You could add this in the function deleteAllFiles() before deleting anything. If you need an example just say, and ill write one.Cyathus
@RonnieOosting I am talking about doing the test with phpunit.Epithelioma
Can you show us how you are calling the Job from your controller (or wherever else you're calling it from)?Bronchitis
@Bronchitis It will be calling from the controller. eg: dispatch(new ActionJob(['action' => 'deleteAllFiles']));Epithelioma
B
6

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';
});
Bronchitis answered 30/9, 2017 at 16:2 Comment(4)
Ah I see, it make sense now. Can you provide example of mocking deleteAllFiles() method assuming returned true and handle() has to be called.Epithelioma
In this approach, you assert on the data, not that specific methods are called. I'd post another question specifically about mocking since that isn't specifically tied to Laravel. For learning more about mocking, this helped me a lot: jtreminio.com/2013/03/…Bronchitis
Thank you. It look like I will have to do something like $job = new ActionJob(...); $job->handle(); in the Test. I thought Queue::fake(); would call handle() automatically.Epithelioma
No. The main point of faking it is to assert that it is queued or dispatched.Bronchitis

© 2022 - 2024 — McMap. All rights reserved.