pushkidman's avatar

How to test chained jobs in Laravel 10?

I am using Laravel 10 and recently developed chunked download feature which takes advantage of Laravel's chained jobs. The feature creates several jobs based on chunk size and number of items to download and runs one job in the end to notify the user.

$jobChain = [];
foreach ($listIds as $listId) {
    $chunkCount = $count > self::BATCH_SIZE ? ceil($count / self::CHUNK_SIZE) : 1;
    $offset = 0;
    $limit = self::CHUNK_SIZE;
    for ($i = 0; $i < $chunkCount; $i++) {
       $jobChain[] = new DownloadJob($import, $listId, $accessToken, $apiEndpoint, $limit, $offset);
       $limit += self::CHUNK_SIZE;
       $offset += self::CHUNK_SIZE;
   }
}

$jobChain[] = new NotificationJob($this->import, $this->user, 'success');

Bus::chain($jobChain)->onQueue($queueName)->dispatch();

The feature works well but trying to test cover it is a hair-pulling experience.

The following scenario did not work (failed with false), so I assume chained jobs cannot be tested with fake queue:

Queue::fake();
...
Queue::assertPushedWithChain(DownloadJob::class, [
     DownloadJob::class,
     DownloadJob::class,
     NotificationJob::class
]);

Tried to test by faking the Bus. The most basic example worked:

Bus::assertChained([
     DownloadJob::class,
     DownloadJob::class,
     NotificationJob::class,
]);

However, I would also like to test out the params.

The following assertion was also successful:

Bus::assertChained([
      function(DownloadJob $job) use ($import, $lists) {
          return $import->id === $job->import->id && $job->listId === $lists[0];
      },
      DownloadJob::class,
      NotificationJob::class,
]);

However, the following did not:

Bus::assertChained([
      function(DownloadJob $job) use ($import, $lists) {
          return $import->id === $job->import->id && $job->listId === $lists[0];
      },
      function(DownloadJob $job) use ($import, $lists) {
          return $import->id === $job->import->id && $job->listId === $lists[1];
      },
      function(NotificationJob $job) use ($import) {
          return $import->id === $job->import->id;
      },
 ]);

I am 100% sure that params are correct as I debugged the actual array with var_dump($jobChained)

My last resort was

Bus::assertChained([
     new DownloadJob($import, $lists[0], $accessToken, $apiEndpoint, 10000, 0),
     new DownloadJob($import, $lists[1], $accessToken, $apiEndpoint, 10000, 0),
     new NotificationJob($import, $this->user, 'success'),
]);

but surprise-surprise - it did not work either.

At that point I am clueless how to move-on. Debugging the code inside BusFake class does not seem to be worth but looks like the only way as the test scenarios for the feature are very poorly documented.

Does anyone have experience with that?

0 likes
0 replies

Please or to participate in this conversation.