Skip to content

PhpUnit Dataprovider from abstract class fails. #6549

@Basster

Description

@Basster

What are you trying to achieve?

We currently migrate from PhpUnit to Codeception and moved our unit tests to tests/Unit.

We discovered that the PhpUnit test wrapper, especially the DataProvider loader could not load data from test classes, where the actual test, defining the dataProvider, is in an abstract class.

Example
<?php

declare(strict_types=1);

namespace App\Tests\Unit;

use PHPUnit\Framework\TestCase;

/**
 * Class EventSubscriberTestCase.
 */
abstract class EventSubscriberTestCase extends TestCase
{
    /**
     * @test
     * @dataProvider provideSubscribedEvents
     */
    public function subscribesEvent(string $eventName): void
    {
        $events = $this->getSubscriberClassName()::getSubscribedEvents(); // @phpstan-ignore-line
        if (is_iterable($events) && !\is_array($events)) {
            $events = iterator_to_array($events);
        }
        self::assertArrayHasKey($eventName, $events);
    }

    /**
     * @phpstan-return iterable<string, array<string>>
     */
    public function provideSubscribedEvents(): iterable
    {
        $subscribe = $this->shouldSubscribeEvents();

        foreach ($subscribe as $event) {
            yield $event => [$event];
        }
    }

    /**
     * @phpstan-return iterable<array-key, string>
     */
    abstract protected function shouldSubscribeEvents(): iterable;

    /**
     * @return class-string
     */
    abstract protected function getSubscriberClassName(): string;
}

###

<?php

declare(strict_types=1);

namespace App\Tests\Unit\EventSubscriber;

use App\Tests\Unit\EventSubscriberTestCase;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * @internal
 */
final class MyKernelControllerEventSubscriberTest extends EventSubscriberTestCase
{
    protected function shouldSubscribeEvents(): iterable
    {
        yield KernelEvents::CONTROLLER;
    }

    protected function getSubscriberClassName(): string
    {
        return MyKernelControllerEventSubscriber::class;
    }
}

What do you get instead?

Provide console output if related. Use -vvv mode for more details.

ErrorTestCase: Error
 Test  vendor/phpunit/phpunit/src/Framework/ErrorTestCase.php:Error
                                                                                                                                                                                                                        
  [PHPUnit\Framework\Error] The data provider specified for App\Tests\Unit\EventSubscriber\MyKernelControllerEventSubscriberTest:subscribesEvent is invalid.
Cannot instantiate abstract class App\Tests\Unit\EventSubscriberTestCase                                                          

Details

  • Codeception version: 5.0.0
  • PHP Version: 8.1.5

I've already prepared a fix, which I'll submit in a few minutes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions