I had previously shared an annoyance I ran into testing a command with validation logic. Claude Code tried to work around it by putting exception handling logic in my test, but I rejected that solution.
My solution was to improve the command and not just paper over the exception in my test.
Instead of just calling validated() and letting it throw, I first check whether validation fails and gracefully handle it:
if ($validator->fails()) {
collect($validator->errors()->all())
->each(fn ($message) => $this->error($message));
return static::FAILURE;
}
// this will never throw an exception now
$arguments = $validator->validated();
Now the command runs without blowing up, and it produces clear error output and an exit code to tell the caller what went wrong.
This improved logic not only produces a better user experience, it also solves my testing friction from the unhandled exception.
Instead of introducing exception handling to my test, I have a clean chained assertion:
$this->artisan(TipsCreateBook::class, ['from' => ''])
->assertExitCode(Command::FAILURE)
->expectsOutput('The from field is required.');
I like this solution a lot better!
Here to help,
Joel
P.S. We go deep on testing techniques like this in our hands-on workshop. Check out our testing workshop.