symfony: [Framework bundle] Cleanup error and exception handlers on Kernel shutdown
Symfony version(s) affected
7.0.0
Description
PHPUnit 11 checks for any leftovers in error handlers https://github.com/sebastianbergmann/phpunit/pull/5619
How to reproduce
Run FrameworkBundle->boot() in phpunit test.
It results in Test code or tested code did not remove its own exception handlers thrown by phpunit.
Possible Solution
Introduce FrameworkBundle::shutdown() that would cleanup error handler set in boot(). IMO it’s reasonable to have some cleanup in shutdown() of things initiated in boot().
Additional Context
No response
About this issue
- Original URL
- State: open
- Created 5 months ago
- Reactions: 15
- Comments: 16 (11 by maintainers)
Commits related to this issue
- Update phpunit-bootstrap.php workaround for https://github.com/symfony/symfony/issues/53812#issuecomment-1962311843 — committed to TurboLabIt/webstackup by ZaneCEO 4 months ago
- chore(ci): use phpunit version 9 otherwise risky checks are warned https://github.com/symfony/symfony/issues/53812 — committed to whatwedo/MonitorBundle by xarem 4 months ago
- fix: Исправление ошибки Test code or tested code did not remove its own exception handlers Фикс взят из https://github.com/symfony/symfony/issues/53812 — committed to muratsalakhov/twitter-symfony by muratsalakhov 3 months ago
A different workaround, seeing as the Symfony/Errorhandler is a singleton and will only register once, is to register the error handler before phpunit memorizes all the existing error handlers. This way the error handler Symfony register’s is not new.
Create (or modify)
/tests/bootstrap.php:and in
phpunit.xml@frankdekker is right, the error handler registered by FrameworkBundle would not replace the active error handler. PHPUnit already registers its own error handler and that one is still active at the end of the test. So we’re good here.
The problem which PHPUnit reports is about the exception handler. Yes, error handler and exception handler are two different things. And yes, it’s super confusing that Symfony has a method called
ErrorHandler::register()that registers an error handler and and exception handler. 😓PHPUnit on the other hand does not register an exception handler and even if it did, that handler would be wrapped by
ErrorHandler::register()which PHPUnit would still rightfully complain about.But.
ErrorHandlerwon’t replace the exception handler ifErrorHandleralready is the current exception handler. This means, we can simplify @frankdekker’s bootstrap script like this:That being said, this feels like a hack. Maybe we should add a way to opt out of the exception handler. In situations where the kernel is executed within a huge try/catch block (which a PHPUnit test basically is), that exception handler does not serve any purpose anyway.
Same issue “Test code or tested code did not remove its own exception handlers” here with
What if we stopped registering error handlers, exception handlers or shutdown functions of any kind in FrameworkBundle?
We do need this stuff way before the framework is booted, so whatever FrameworkBundle registers here, it does it way too late. This applies especially to exception handlers: They are meant to handle uncaught exceptions. The kernel however runs in a big try/catch, so at the time FrameworkBundle is booted, the need for an exception handler is more or less over.
In modern Symfony applications, the error handling should be set up by the runtime already. All that FrameworkBundle does is connecting the logger properly. The logic that registers an error handler or exception handler is usually dormant and causes trouble because PHPUnit tests run outside of the runtime.
I had the same problem with Symfony 6.4 and PHPUnit 11. I temporarily solved it by calling this method in the
tearDownof my base test case (which extends fromKernelTestCaseorWebTestCase):The
tearDownlooks like this:It is based on what Laravel did on their testsuite: https://github.com/laravel/framework/pull/49622/files
Maybe the solution is to call a similar method in the
tearDownofKernelTestCaseandWebTestCase?This issue is a blocker for PHPUnit 11 in any Symfony project that uses
KernelTestCaseorWebTestCase. Given that PHPUnit comes with its own error handler, maybe the solution would be to opt out of Symfony’s own error handler when booting the kernel for functional tests?Recently created a new Project with the Lumen Framework and wrote Tests for it and got this Warnings:
* Test code or tested code did not remove its own error handlers * Test code or tested code did not remove its own exception handlers
To overcome this Problem I needed to put this in the TestCase Class:
I hope this helps others, too.
This will be resolved by whomever resolves it. Could be you?
Will this issue be resolved by symfony or is it expected to add @derrabus solution to every project?
this is not a root cause. I’d correct that to:
E.g. for me the test maintenance is much easier when I’m not relying on SF testcases so I can extend my own leaner testcase. I use Kernel via composition in tests.
So the root cause is that there’s no way to cleanup after Kernel, not some test case.