dg / bypass-finals

Removes `final` and `readonly` keywords from source code on-the-fly and allows mocking of final methods and classes. It can be used together with any test tool such as PHPUnit or Mockery.
Other
487 stars 30 forks source link

Phpunit 10 doesn't works with bypass-finals #38

Closed savinnorse closed 1 year ago

savinnorse commented 1 year ago

`An error occurred inside PHPUnit.

Message: call_user_func(): Argument #1 ($callback) must be a valid callback, class "PHPUnit\Util\ErrorHandler" not found Location: /Users/aleksandrsavin/norse/api/vendor/symfony/phpunit-bridge/DeprecationErrorHandler.php:126

0 [internal function]: Symfony\Bridge\PhpUnit\DeprecationErrorHandler->handleError(2, 'stat(): stat fa...', '/Users/aleksand...', 206)

1 /Users/aleksandrsavin/norse/api/vendor/dg/bypass-finals/src/NativeWrapper.php(206): stat('/Users/aleksand...')

2 /Users/aleksandrsavin/norse/api/vendor/dg/bypass-finals/src/NativeWrapper.php(193): DG\NativeWrapper->native('stat', '/Users/aleksand...')

3 /Users/aleksandrsavin/norse/api/vendor/dg/bypass-finals/src/BypassFinals.php(173): DG\NativeWrapper->url_stat('/Users/aleksand...', 6)

4 [internal function]: DG\BypassFinals->__call('url_stat', Array)

5 /Users/aleksandrsavin/norse/api/vendor/phpunit/phpunit/src/Runner/ResultCache/DefaultResultCache.php(56): is_dir('/Users/aleksand...')

6 /Users/aleksandrsavin/norse/api/vendor/phpunit/phpunit/src/TextUI/Application.php(586): PHPUnit\Runner\ResultCache\DefaultResultCache->__construct('/Users/aleksand...')

7 /Users/aleksandrsavin/norse/api/vendor/phpunit/phpunit/src/TextUI/Application.php(159): PHPUnit\TextUI\Application->initializeTestResultCache(Object(PHPUnit\TextUI\Configuration\Configuration))

8 /Users/aleksandrsavin/norse/api/vendor/phpunit/phpunit/phpunit(99): PHPUnit\TextUI\Application->run(Array)

9 /Users/aleksandrsavin/norse/api/vendor/bin/phpunit(123): include('/Users/aleksand...')

10 /private/var/folders/fl/4xt09qyx6_g6c4s87yrq3vs80000gn/T/ide-phpunit.php(224): require_once('/Users/aleksand...')

11 /private/var/folders/fl/4xt09qyx6_g6c4s87yrq3vs80000gn/T/ide-phpunit.php(173): IDE_PHPUnit_Loader::loadByAutoloader('/Users/aleksand...')

12 /private/var/folders/fl/4xt09qyx6_g6c4s87yrq3vs80000gn/T/ide-phpunit.php(228): IDE_PHPUnit_Loader::init()

13 {main}`

do you have in plans to adapt bypass for phpunit 10?

dg commented 1 year ago

Hi, I don't use phpunit, so it would be nice if you (or someone else) would resolve this and send a PR

savinnorse commented 1 year ago

thanks for your response. after more investigations, I found that the issue was not in bypass, but in phpunit-bridge and it has been already fixed on version 6.2.10.

binarious commented 1 year ago

Well it doesn't work for me in combination with mockery:

Failed asserting that exception message 'The class \MyVendor\MyBundle\Service\Inbox\MyService\MyServiceSoapClient is marked final and its methods cannot be replaced. C
lasses marked final can be passed in to \Mockery::mock() as instantiated objects to create a partial mock, but only if the mock is not subject to type hinting checks.' contains 'Expected Error'.
$myserviceSoapClient = \Mockery::mock(MyServiceSoapClient::class);
    <extensions>
        <extension class="MyVendor\MyBundle\tests\Hooks\BypassFinalHook"/>
    </extensions>
<?php

namespace MyVendor\MyBundle\tests\Hooks;

use DG\BypassFinals;
use PHPUnit\Runner\BeforeTestHook;

final class BypassFinalHook implements BeforeTestHook
{
    /** @inheritDoc */
    public function executeBeforeTest(string $test): void
    {
        BypassFinals::enable();
    }
}

Any ideas?

EDIT: nvm: https://github.com/sebastianbergmann/phpunit/issues/4595

savinnorse commented 1 year ago

1) To check that the issue is not with hook call try to add bypassfinals::enable(); just before mock creating 2) if still have issue check what versions are u using. Bypass and phpunit. For me it was issue that was fixed by updating phpunit-bridge to the last minor version

ratenfanger commented 1 year ago

Enabling BypassFinals is quite easy with the new extension system of PHPUnit 10. Just create an extension:

final class BypassFinalExtension implements \PHPUnit\Runner\Extension\Extension
{
    public function bootstrap(Configuration $configuration, Facade $facade, ParameterCollection $parameters): void
    {
        BypassFinals::enable();
    }
}

And at it to the PHPUnit configuration:

<extensions>
    <bootstrap class="App\Tests\Extensions\BypassFinalExtension"/>
</extensions>
dg commented 1 year ago

I added the extension directly to the repository efe2fe04bae9f0de271dd462afc049067889e6d1