Basster · GitHub

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.

Read the original on github.com ↗