-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Description
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