Skip to content

PHPUnit assertion exception caught in code under test, not failing the test #6372

@thePanz

Description

@thePanz
Q A
PHPUnit version 12.3.15
PHP version 8.3.22
Installation Method PHAR

Summary

A failing assertion within a ::willReturnCallback(function () { }) triggers the PHPUnit exception to be caught in the code under test, not failing the test itself.

I tried to replicate the code under test here below.
Please let me know if you need more clarity on this case, it is quite confusing to me too 😓

I discovered this case while running infection-php: which marked some mutations not being covered, while (from a first sight) they actually are.

Current behavior

A PHPUnit assertion exception is caught, and the test not marked as failed.

How to reproduce

Given the following 2 classes, and the test BarTest.
The test is not failing in the $this->assertSame('foo-foo', $param); as the PHPUnit exception is caught in the Bar::doBar() code instead

<?php

class Foo {
    public function doFoo(string $param): void {}
}

class Bar {
    public function __construct(private readonly Foo $foo) {}

    public function doBar(string $param): void
    {
        try {
            $this->foo->doFoo($param);
        } catch (\Exception $e) {
            // Looks like the PHPUnit exception is received here
            // It is "Can not assert that "foo-foo" is the same as "bar-bar"
            // ... but I would expect it to FAIL the test scenario, not to get an exception handled in my code
        }
    }
}

class BarTest extends \PHPUnit\Framework\TestCase
{
    public function testBarDoBar(): void
    {
        $mockFoo = $this->createMock(Foo::class);
        $mockFoo->expects($this->once())
            ->method('doFoo')
            ->willReturnCallback(function (string $param): void {
                // This is just an example, as the real parameter is a DTO, where we are testing that all properties are
                // correct according to some other 
                $this->assertSame('foo-foo', $param);
            });

        $bar = new Bar($mockFoo);
        $bar->doBar('bar-bar');
    }
}

Expected behavior

The test case should FAIL, without the PHPUnit exception being caught in the code under test

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions