logo

Asserting that nothing went wrong

PHPUnit doesn't have this built in, so we wrote it ourselves

Joel Clermont
Joel Clermont
2026-05-12

Sometimes the only thing a test is checking is that the code didn't blow up. Maybe you're calling a service where success is silent, and you want a test that says "this ran and nothing was thrown."

PHPUnit has expectException for the opposite case, but it has no built-in assertion for "no exception was thrown." If you write the test the obvious way, PHPUnit flags it as risky because no assertion was performed.

public function testJobCompletesWithoutThrowing(): void
{
    $job = new SyncCustomerJob($customer);
    $job->handle();
    
    // nothing blew up, our test should pass
}

That comment helps a human reader spot the intent, but PHPUnit doesn't read comments. You'll still see the risky test warning.

The smallest fix is addToAssertionCount.

public function testJobCompletesWithoutThrowing(): void
{
    $job = new SyncCustomerJob($customer);
    $job->handle();

    $this->addToAssertionCount(1);
}

That tells PHPUnit you did one assertion's worth of work, even though no assert* method ran.

If you reach for this in more than a handful of tests, wrap it in a helper so the call site is self-documenting. You could put this in your base test case or a trait to make it easy to re-use across test classes.

/**
 * PHPUnit doesn't let us assert that no exceptions were thrown
 * This is a workaround to also avoid flagging a test as risky
 */
protected function assertNoExceptionsThrown(): void
{
    $this->addToAssertionCount(1);
}

Now the intent is right there in the method name.

$job->handle();
$this->assertNoExceptionsThrown();

Here to help,

Joel

P.S. Want to write tests that read like documentation? Small patterns like this are what our testing workshop is full of.

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.