logo

PHPUnit can mark a test as deliberately quiet

And there's one catch worth knowing

Joel Clermont
Joel Clermont
2026-05-14

In a previous tip, I shared the assertNoExceptionsThrown helper we use to satisfy PHPUnit when a test's only job is to verify nothing was thrown.

The helper works by calling addToAssertionCount(1), which bumps the counter to keep PHPUnit happy. It's a small lie. The test technically asserted nothing, but we tell PHPUnit it asserted something.

PHPUnit has a more honest method for the same situation.

public function testJobCompletesWithoutThrowing(): void
{
    $this->expectNotToPerformAssertions();

    $job = new SyncCustomerJob($customer);
    $job->handle();
}

expectNotToPerformAssertions() is a declaration of intent. You're telling PHPUnit "this test is deliberately checking that the code runs and nothing else." The risky warning goes away because you've explicitly opted out of needing assertions.

There's a flip side worth knowing. If your test secretly does run an assertion (a Mail fake, a Mockery expectation, or any assert* call), PHPUnit flags the test as risky for the opposite reason.

This test is not expected to perform assertions but performed N assertions

That's why addToAssertionCount still has a place. Sometimes a test does have real assertions, but also has a branch where the only thing happening is a side effect like an exception being caught.

public function testRateLimited(): void
{
    Mail::fake();

    for ($i = 0; $i < 5; $i++) {
        $this->postLogin('');
    }

    try {
        $this->postLogin('');
    } catch (ThrottleRequestsException $e) {
        $this->addToAssertionCount(1);
    }

    Mail::assertNothingOutgoing();
}

The addToAssertionCount(1) is marking "yes, the throttle exception fired." The Mail::assertNothingOutgoing() is a real assertion. If we replaced our assertion count with expectNotToPerformAssertions() at the top, the test would be flagged risky because the Mail assertion would still run.

My rule of thumb is short. If the whole test has nothing to assert, reach for expectNotToPerformAssertions(). If one branch of the test has nothing to assert but the test still has real assertions elsewhere, stick with addToAssertionCount(1).

Here to help,

Joel

P.S. Knowing which PHPUnit convention to reach for is a tiny skill that compounds over a long-lived test suite. We go deep on patterns like this in our testing workshop.

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.