When it comes to Queue testing in Laravel, I use the provided Queue Fake functionality. However, there is a case where I need to create a Mock for a Job class.
I have the following code that pushes a job to a Redis powered queue:
$apiRequest->storeRequestedData($requestedData); // a db model
// try-catch block in case the Redis server is down
try {
AppJobsProcessRunEndpoint::dispatch($apiRequest)->onQueue('run');
$apiRequest->markJobQueued();
} catch (Exception $e) {
//handle the case when the job is not pushed to the queue
}
I need to be able to test the code in the catch block. Because of that, I’m trying to mock the Job object in order to be able to create a faker that will throw an exception.
I tried this in my Unit test:
ProcessRunEndpoint::shouldReceive('dispatch');
That code returns: Error: Call to undefined method AppJobsProcessRunEndpoint::shouldReceive()
.
I also tried to swap the job instance with a mock object using $this->instance()
but it didn’t work as well.
That said, how can I test the code in the catch block?
2
Answers
I found a solution. Instead of using a facade for adding a job to the queue (
AppJobsProcessRunEndpoint::dispatch($apiRequest)->onQueue('run');
), I injected it into the action of the controller:With this, the job object is resolved from the container, so it can be mocked:
Although still not sure why the
shouldReceive
approach doesn't work for the facade: https://laravel.com/docs/8.x/mocking#mocking-facadesAccording to the docs, you should be able to test jobs through the mocks provided for the Queue.
Making the line
AppJobsProcessRunEndpoint::dispatch($apiRequest)->onQueue('run');
throw an exception is a bit complicated.dispatch()
just returns an object andonQueue()
is just a setter. No other logic is done there. Instead, we can make everything fail by messing with the configuration.Instead of
Queue::fake();
, override default queue driver with one that just won’t work:Queue::setDefaultDriver('this-driver-does-not-exist');
This will make every job dispatch fail and throw anErrorException
.Minimalist example: