Asserting Jobs in Queue with Laravel Dusk

When writing end-to-end tests with Laravel Dusk, you cannot mock your job dispatches like you use to do in Laravel 5.3 because the browser is a separate process and any tweaks you do inside your tests doesn’t exist when the browser hits the application. The browser will bootstrap the whole application again. My workaround for this was to simply assert that the job is in the queue to be dispatched with some simple steps.

Setup a Dusk Queue that uses the Database

Open your config/queue.php file and setup a Queue exclusively for Dusk. Keep your focus on the connection name defined in the key of the array and the queue name defined in the queue index.

'connections' => [

'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,
],

'dusk-connection' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'dusk-queue',
'retry_after' => 90,
],

]

Dusk Environment

In your .env.dusk.local file, set QUEUE_DRIVER to dusk-connection. Special attention to how Dusk swaps environments.

Make sure the Jobs table exists

If you haven’t already, run php artisan queue:table to create a migration for the jobs table and then run php artisan migrate to run the newly created migration against your database.

Add Custom assertion to DuskTestCase.php

If you’ve installed Dusk, you noticed that it created the file tests/DuskTestCase.php. Let’s add a custom assertion into this file. 
NOTE: We want to pop the next job available in the dusk-queue, which is the queue name chosen in the setup step.

/**
* Asserts that Jobs are in Queue to be dispatched.
*
*
@param array|string $queued
*/
public function assertQueued($queued) {
if (!is_array($queued))
$queued = func_get_args();

$repository = app()->make(
\Illuminate\Contracts\Queue\Queue::class
);

foreach ($queued as $item) {
$job = $repository->pop('dusk-queue');
$this->assertTrue($job->resolveName() == $item);
}
}

Test your job!

For this example, I created two sample jobs called MyFirstJob and MySecondJob by running php artisan make:job MyFirstJob and php artisan make:job MySecondJob. assertQueued will accept multiple parameters, an array of parameters or just a single qualified class.

Route::get('/', function () {
dispatch(new \App\Jobs\MySecondJob);
dispatch(new \App\Jobs\MyFirstJob);
return view('welcome');
});
public function testBasicExample()
{
$this->browse(function (Browser $browser) {
$browser->visit('/')
->assertSee('Laravel');
});

$this->assertQueued([MyFirstJob::class, MySecondJob::class]);
}

Conclusion

Dusk will navigate to your application, trigger some event that queues a job in the jobs table using QUEUE_DRIVER=dusk-connection. You can, then, assert that this job is in the database from Dusk itself. But be aware: you need to make sure your tests builds a clean database and tears it down for each test, otherwise popping the next job might not work as expected.

Hacker Noon is how hackers start their afternoons. We’re a part of the @AMI family. We are now accepting submissions and happy to discuss advertising & sponsorship opportunities.
If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!

More by Marco Aurélio Deleu

Topics of interest

More Related Stories