logo

What if you can't make your code fail in a test?

Maybe it can't fail at all

Joel Clermont
Joel Clermont
2026-11-03

A student in my testing course asked me how to test a try/catch block. The method wrapped a few database calls, caught any exception, logged it, and returned false. Otherwise, it returned true.

They couldn't figure out how to make the database throw an exception in a test. And they didn't want to mock the model just to force one.

So I asked them what failure that catch block was meant to handle. They thought about it for a minute, and the only answer was the database going down entirely. That's truly exceptional, and Laravel's exception handler already logs and reports it.

That's a useful insight. If you can't make code fail in a test, ask yourself whether it can fail in production in a way this code can handle. And if it can't, maybe the code shouldn't be there.

Defensive code written "just in case" might seem harmless, or even cautious, but it's really just one more branch to read, maintain, and yes, test.

So in this case, the right question to think about isn't how to test the catch block, but whether the catch block is even needed at all.

If it really is needed, then jump up a layer. The calling code decides what the user sees when the method returns false, so test that instead. Mocking the service at that boundary is easy:

public function testCheckoutShowsErrorWhenOrderFails(): void
{
    $this->mock(OrderService::class)
        ->shouldReceive('place')
        ->andReturnFalse();

    $this->post(route('checkout.store'))
        ->assertSessionHasErrors('order');
}

100% code coverage is never the goal. Confidence that your app behaves correctly is what we really want.

Here to help,

Joel

P.S. Our testing course walks through mocking a service like this, plus how to use test coverage as a guide instead of a goal.

Toss a coin in the jar if you found this helpful.
Want a tip like this in your inbox every weekday? Sign up below 👇🏼
email
No spam. Only real-world advice.