Codeception / module-doctrine

Next gen Doctrine module for Codeception
MIT License
2 stars 1 forks source link

loadFixtures() doesn't work with Symfony's dependency injection #12

Open ThomasLandauer opened 3 years ago

ThomasLandauer commented 3 years ago

When the fixture class is a Symfony service with normal dependency injection (i.e. constructor arguments), loading them with $I->loadFixtures(AppFixtures::class) leads to this error message:

[ArgumentCountError] Too few arguments to function App\DataFixtures\AppFixtures::__construct(), 0 passed in /.../vendor/codeception/module-doctrine2/src/Codeception/Module/Doctrine2.php on line 731 and exactly 4 expected

TavoNiievez commented 3 years ago

Hmm... DataFixtures are not supposed to be services in Symfony, in some projects it's even usually excluded next to the entities and migrations folder, are you sure you don't have them excluded as services in your services.yaml?

ThomasLandauer commented 3 years ago

Well, declaring the fixture class as a service isn't anything special - it's even explained at https://symfony.com/doc/3.1/bundles/DoctrineFixturesBundle/index.html#accessing-services-from-the-fixtures

Your fixtures class is a service, so you can use normal dependency injection:

I'm using it this way to inject some helpers and some Symfony parameters. So yes, I'm sure they're not excluded - otherwise the dependency injection wouldn't work when I load the fixtures :-)

TavoNiievez commented 3 years ago

Oh, i see...

It seems i had misinterpreted your problem. I'm sorry.

I've had problems like that before, for example when using Setter Injection in some trait. Try to:

Get the services your fixtures need from the container and create the Fixture object passing them as arguments.

        $service = $this->tester->grabService(Service::class);
        $this->fixtures = new Fixture($service);
        $this->fixtures->load();

Now why those specific services are not injected automatically is a different problem. I think it may have something to do with the test container configuration... but you will find out if the ->grabService() method does not return the expected object.

ThomasLandauer commented 3 years ago

Here's the workaround I'm using right now:

use Doctrine\Common\DataFixtures\Purger\ORMPurger;
$purger = new ORMPurger($this->entityManager);
$purger->purge();
$this->appFixtures->load($this->entityManager);

This looks easier to me, cause with your way I'd have to manually keep the order of constructor arguments in sync, right?

Now why those specific services are not injected automatically is a different problem.

Well, this is the issue I'm talking about :-)

I think it may have something to do with the test container configuration... but you will find out if the ->grabService() method does not return the expected object.

OK, but which is the expected object? After all, my plan would be not to use ->grabService() at all, but just $I->loadFixtures(AppFixtures::class) to load the fixtures :-)

So would you say this is a bug that can be fixed? Or is this the expected behavior (or just the way it is) - then I'd mention it in the docs of loadFixtures().

luninroman commented 1 week ago

Hi guys, is there any update on this? The official doc says it's legit to inject services into fixtures.