Occasionally, when running a test, this error comes up when a test fails:
PHP Fatal error: Method PHPUnit_Framework_ExpectationFailedException::__toString() must not throw an exception in phar:///usr/local/bin/phpunit/phpunit/TextUI/ResultPrinter.php on line 0
Any simple failure can trigger this error. I tried using a try/catch on my autoloader to see if there were any classes from PHPUnit that my autoloader shouldn't be trying to load, as I had a previous problem with my autoloader trying to load the now deprecated PHPUnit_Extensions_Story_TestCase, but did not catch anything. I'm not too entirely sure how to properly replicate this problem as I can't find a pattern to why the error appears. Sometimes I get the correct failed assertion message instead of the error.
Also, sometimes I get this error instead:
PHP Fatal error: PHP Fatal error: Method PHPUnit_Framework_ExceptionWrapper::__toString() must not throw an exception in phar:///tmp/phpunit.phar/phpunit/TextUI/ResultPrinter.php on line 0
which also came up in this previous thread: https://github.com/sebastianbergmann/phpunit/issues/1485. I tried excluding the Symfony class from my autoloader, but it didn't change anything.
Also, I'm using PHPUnit 4.4.5.
Does your autoloader throw an exception when it can't find a class?
Yes, it throws Exception: include_once(nonExistantClass.php): failed to open stream: No such file or directory
Your autoloader must do anything for code that it is not responsible for.
Are you saying that my autoloader is trying to load a class it shouldn't to get the PHPUnit_Framework_ExpectationFailedException error? Is there a way to pinpoint this class? Because when I put my autoloader inside a try/catch, it doesn't catch anything.
I'm having the same problem. To fix that i had to change the line 93 of the PHPUnit_Util_Blacklist class:
FROM:
...
if (!class_exists($className)) {
...
TO:
..
if (!class_exists($className, false)) {
..
Why? I dont think you have to call autoload in this case, since this is only checking for the classes loaded which will be filtered.
Same issue. I think Sebastian meant "Your autoloader must NOT do anything for code that it is not responsible for." E.g. if your code registers an exception handler or shutdown function via set_exception_handler or register_shutdown_function and there's an exception thrown anywhere in there, that can trigger this PHPUnit error.
How come this still isn't fixed after all this time? All that's needed is a simple try-catch in https://github.com/sebastianbergmann/phpunit/blob/master/src/Util/Blacklist.php
Or to disable class auto-loading as cezarpirajant suggests.
In my case, it was the Composer\Autoload\ClassLoader class that was missing and causing the rendering error.
Since I didn't want to patch the PHPUnit library, I ended up doing this inside of my PHPUnit bootstrap instead:
// Remove missing classes from the PHPUnit blacklist, to prevent an exception rendering error.
// Workaround to fix the actual PHPUnit bug (see https://github.com/sebastianbergmann/phpunit/issues/1598).
if (!empty(PHPUnit_Util_Blacklist::$blacklistedClassNames)) {
foreach (PHPUnit_Util_Blacklist::$blacklistedClassNames as $className => $parent) {
try {
if (!class_exists($className)) {
unset(PHPUnit_Util_Blacklist::$blacklistedClassNames[$className]);
}
} catch (Exception $e) {
unset(PHPUnit_Util_Blacklist::$blacklistedClassNames[$className]);
}
}
}
@Malbeth81 What version of PHPUnit are you running? If the fix is really this simple, pull requests for breaking bugs are still accepted for older versions. Is there a self-contained testcase?
I'm using PHPUnit 5.7.26, however as I pointed out, looking at the current master we still see that nothing was changed in that function: https://github.com/sebastianbergmann/phpunit/blob/master/src/Util/Blacklist.php
@Malbeth81 thanks for your reply, but v5 is too far back to receive further updates. There's bugfixes for 6.x, some new features for v7 and a serious refactoring for beyond.
Most helpful comment
I'm having the same problem. To fix that i had to change the line 93 of the PHPUnit_Util_Blacklist class:
FROM:
TO:
Why? I dont think you have to call autoload in this case, since this is only checking for the classes loaded which will be filtered.