Repeated Jobs

Better ways to test same-class jobs

When the same job is dispatched multiple times, standard assertions hide which one failed.

Controller
// app/Http/Controllers/JobController.php
class JobController extends Controller
{
    public function __invoke()
    {
        TestJob::dispatch('John', 30);
        TestJob::dispatch('Will', 20);
    }
}
Standard way (vague)
// tests/Feature/Http/Controllers/JobControllerTest.php
Queue::assertPushed(TestJob::class, 2);

Queue::assertPushed(fn($job) => $job->name === 'John' && $job->age === 30);
Queue::assertPushed(fn($job) => $job->name === 'Will' && $job->age === 20);
Better way (pinpoint exact failures)
// tests/Feature/Http/Controllers/JobControllerTest.php
Queue::assertPushed(TestJob::class, 2);

$index = 0;
$assertions = [
    ['name' => 'John', 'age' => 30],
    ['name' => 'Will', 'age' => 20],
];

Queue::assertPushed(function (TestJob $job) use (&$index, $assertions) {
    $this->assertSame(
        $assertions[$index]['name'],
        $job->name,
        "Job #{$index}: name should be {$assertions[$index]['name']}"
    );

    $this->assertSame(
        $assertions[$index]['age'],
        $job->age,
        "Job #{$index}: age should be {$assertions[$index]['age']}"
    );

    $index++;

    return true;
});

Now you know exactly which job and which parameter failed.

Read more by @jcergolj: Better Ways to Test Repeated Laravel Jobs