phpspec / prophecy

Highly opinionated mocking framework for PHP 5.3+
MIT License
8.53k stars 241 forks source link

Method with an enum argument and default value can't be mocked #567

Closed bicpi closed 5 months ago

bicpi commented 1 year ago

Hi, given this enum (PHP 8.1+):

enum AppType
{
    case IOS;
    case ANDROID;
}

And an interface with a method using the enum as default argument of a method:

interface BarService
{
    public function doIt(AppType $appType = AppType::ANDROID): void;
}

And a service using the interface as a dependency:

class FooService
{
    public function __construct(
        readonly private BarService $bar
    ) {
    }

    public function execute(): void
    {
        $this->bar->doIt();
    }
}

The following test fails:

namespace Tests;

use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;

enum AppType {...}
interface BarService {...}
class FooService {...}

class FooServiceTest extends TestCase
{
    use ProphecyTrait;

    /**
     * @test
     */
    public function it_fails(): void
    {
        $someService = $this->prophesize(BarService::class);
        $someService
            ->doIt()
            ->shouldBeCalled();

        $fooService = new FooService($someService->reveal());
        $fooService->execute();
    }
}

The error message is:

Error : Class "Double\BarService\Tests\AppType" not found

When passing the default value explicitly works though.

stof commented 1 year ago

This error has nothing to do with new in initializers (there is no new in your initializers). It is about support for enums in default values of an argument.

bicpi commented 1 year ago

True, I think I also observed an issue with new usage, I'll refine the description.

stof commented 1 year ago

If there is also an issue with new (which is likely as we haven't done anything to support it), please open a separate issue for it (as the fix might not be the same).

bicpi commented 1 year ago

I reduced this issue to the problem with the enum argument; after testing the case with the new usage in a method's default value, I created the separate issue https://github.com/phpspec/prophecy/issues/568.

lyrixx commented 1 year ago

I confirm the issue.

As soon as a default value is used for an argument typed with a Enum, prophecy crash.

jdreesen commented 5 months ago

I can also confirm this. The problem is, that the generated default value is in the wrong namespace, because the leading \ is missing.

This seems only to be a problem in PHP 8.1, see: https://3v4l.org/3JPCM

I proposed a fix: #618