One of the benefits of Laravel is the way that it sits at your elbow, quietly and effectively taking care of the boring stuff … like whole classes of exceptions – hiding the stack traces away and presenting the consumers of your system with minimal explanations in appropriate formats.
But what about when you, the developer, need to see that detail. For manual browser based testing, not a problem. Set APP_DEBUG=true in your local .env file (which it is by default) and it’s beautifully formatted for you. But nowadays my development is mostly done using Test Driven Development, and all I get to see is the status code to which Laravel has mapped the exception đ
Of course the application error log is still there, sitting in the storage folder. But opening and scrolling down that is tedious. Could there be a better way …?
… happily there is.
All my tests extend the TestCase class that comes as standard with Laravel. It’s likely that yours do to. So placing extra methods in that class makes them available to all your tests.
Here’s one inspired (some might say lifted) from Adam Waltham’s Test Driven Laravel course.
protected function disableExceptionHandling()
{
$this->app->instance(ExceptionHandler::class, new class extends Handler {
public function __construct() {}
public function report(Exception $exception) {}
public function render($request, Exception $exception) {
throw $exception;
}
});
}
When called as part of a phpunit test, or a whole test class through the setUp method, this creates a new minimal exception handler and swaps it for the App\Exception\Handler class that your application would otherwise use. For example:
function testSomethingImportant()
{
$this->disableExceptionHandling();
// carry on with your test as normal
}
This new exception handler suppresses all reporting (so that my Laravel log doesn’t get clogged up with the errors that my TDD approach encourages and, which I’m about to fix anyway.
Even more significantly, instead of rendering the exception, it re-throws it making all that delightful detail available to me as test output. No need to go find it or to break “flow” – just fix it and keep moving forward.
Indeed, I’ve come to depend on it so much that I’ve added a shortcut to my IDE.
Finally, while here, I highly recommend Adam’s Test Driven Laravel course. Some of the best developers I know have taken this and no matter how much of a rock star developer you may be, there’s still plenty to learn from watching how other experts approach their craft.