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.
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,
\],**
]
In your .env.dusk.local
file, set QUEUE_DRIVER
to dusk-connection
. Special attention to how Dusk swaps environments.
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.
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);
}
}
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_\]);
}
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.