Skip to content

dispatchNow() does not call failed() but dispatch() does. #31004

@Patabugen

Description

@Patabugen
  • Laravel Version: 6.5.0
  • PHP Version: 7.3.8
  • Database Driver & Version: n/a

Description:

I'm using MyJob::dispatchNow() in my tests (I'm since aware I can just use MyJob::dispatch() as the driver is set to sync for testing) and running into issues because MyJob::failed is not being called when the job fails (I'm testing my jobs fail nicely).

After digging through the source, it appears that MyJob::failed() is not triggered when using dispatchNow().

I'm not sure whether to report this as a bug in dispatchNow() or just in the documentation which suggests the failed method will always be called if the job fails.

Steps To Reproduce:

Here's a unit test which should illustrate the problem.

  1. Install laravel (or use an existing one)
  2. Save the test below into tests/Unit/TestMyJob.php
  3. Run phpunit tests/Unit/TestMyJob.php
<?php

namespace Tests\Unit;

use Tests\TestCase;

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

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

    public static $putStatusHere = 'pending';

    public function handle()
    {
        self::$putStatusHere = "running";
        throw new \Exception('This job fails!');
    }

    public function failed()
    {
        self::$putStatusHere = "failed";
    }
}

class MyJobTest extends TestCase
{

    public function testFailedGetsCalled()
    {
        $this->assertEquals('pending', MyJob::$putStatusHere);
        // When using dispatchNow() - the failed method does not get called.
        try {
            MyJob::dispatchNow();
        } catch (\Exception $e) {
            // So the status is still 'running' despite the error.
            $this->assertEquals('running', MyJob::$putStatusHere);
        }

        // But whyen using dispatch() the `sync` driver gets used (as per the testing
        // config) and the failed method does get called.
        try {
            MyJob::dispatch();
        } catch (\Exception $e) {
            // Ignore the exception. The point is the job failed.
            $this->assertEquals('failed', MyJob::$putStatusHere);
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions