Testing With Laravel In Maintenance Mode
It is standard in our projects to include simple routes which are used to signify if the application is alive and working. They are primarily polled by Kubernetes liveness probes. The tests are about as simple as they get:
test('Live endpoint is accessible', function () {
get(route('health::live'))->assertStatus(204);
});
There is an edge case though. When an application is put into maintenance mode all routes return HTTP503. This makes sense for other routes but not the liveness one. The app is still alive. Laravel allows you to define a list of routes in the PreventRequestsDuringMaintenance
class which should still be reachable. The challenge comes when adding a test:
test('Live endpoint is accessible when maintenance mode is active', function () {
Artisan::call('down');
get(route('health::live'))->assertStatus(204);
Artisan::call('up');
});
This works.. Most of the time or when run on its own.. Classic race condition. We run tests in parallel to speed them up but this means if tests have any side effects other tests can be affected. Calling Artisan::call('down');
has the side effect of creating a file on disk.
The trick is to use a relatively new feature of Laravel to store the Maintenance Mode flag not in a file but in the cache. This works because when tests are run the cache driver is set to array
. This eliminates the side-effect and gives stable tests.
Simply change config/app.php
:
/*
|--------------------------------------------------------------------------
| Maintenance Mode Driver
|--------------------------------------------------------------------------
|
| These configuration options determine the driver used to determine and
| manage Laravel's "maintenance mode" status. The "cache" driver will
| allow maintenance mode to be controlled across multiple machines.
|
| Supported drivers: "file", "cache"
|
*/
'maintenance' => [
'driver' => 'cache',
// 'store' => 'redis',
],