Closed guillaume-a closed 5 years ago
Hi there!
Where does the $this->loadFixtures() method come from? I’m not familiar with it.
This metho appears to be circumventing the normal way that the fixtures are loaded. I can’t give more directions because I’m not at a computer, but the way you are loading the fixtures is at the root of the problem.
Cheers!
Hi,
$this->loadFixtures()
comes from Liip\FunctionalTestBundle\Test\WebTestCase
, the FunctionalTestBundle I use for functionnal testing on symfony.
And they have a chapter on fixtures which I followed.
Regards.
@guillaume-a tell me please how you solved that?
imports :
- { resource: '../../parameters.xml' }
doctrine:
dbal:
default_connection: default
connections :
default:
driver : pdo_sqlite
path : '%kernel.cache_dir%/test.db'
memory : false
charset: UTF8
services test
<services>
<defaults autowire="true"
autoconfigure="true"
public="false"
>
</defaults>
<service id="RoleFactoryInterface"
alias="App\Factory\RoleFactoryInterface"
public="true"
/>
<service id="UserFactoryInterface"
alias="App\Factory\UserFactoryInterface"
public="true"
/>
</services>
tests setUp()
$container = static::$container;
$loader = new ContainerAwareLoader($container);
$entityManager = $this->getEntityManager();
$referenceFixturesRepository = new ReferenceRepository($entityManager);
$roleFactory = $container->get(RoleFactoryInterface::class);
$roleFixtures = new RoleFixtures($roleFactory);
$roleFixtures->setReferenceRepository($referenceFixturesRepository);
$roleFixtures->setContainer($container);
$loader->addFixture($roleFixtures);
$userFactory = $container->get(UserFactoryInterface::class);
$userFixtures = new UserFixtures($userFactory);
$userFixtures->setReferenceRepository($referenceFixturesRepository);
$userFixtures->setContainer($container);
$loader->addFixture($userFixtures);
ERROR
ArgumentCountError: Too few arguments to function App\DataFixtures\RoleFixtures::__construct(), 0 passed in /var/www/hint/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Loader.php on line 193 and exactly 1 expected
Because of
abstract class AbstractDataFixture extends Fixture implements ContainerAwareInterface{
private $container;
public function load(ObjectManager $manager) : void {
if (null === $this->container) {
throw new InvalidArgumentException(\sprintf('Expected %s got %s', ContainerInterface::class, 'null'));
}
$kernel = $this->container->get('kernel');
if (true === \in_array($kernel->getEnvironment(), $this->environments(), true)) {
$this->doLoad($manager);
}
}
....
final class UserFixtures extends AbstractDataFixture implements DependentFixtureInterface{
private $userFactory;
public function __construct(UserFactoryInterface $userFactory) {
$this->userFactory = $userFactory;
}
public function getDependencies() : array {
return [
RoleFixtures::class, // this
];
}
....
Same for other fixtures
Information for Service "App\DataFixtures\RoleFixtures"
==================================================================================
---------------- ----------------------------------------------------------
Option Value
---------------- ----------------------------------------------------------
Service ID App\DataFixtures\RoleFixtures
Class App\DataFixtures\RoleFixtures
Tags doctrine.fixture.orm
Public no
Synthetic no
Lazy no
Shared yes
Abstract no
Autowired yes
Autoconfigured yes
Error even when loaded from container
$roleFixtures = $container->get(RoleFixtures::class);
$loader->addFixture($roleFixtures);
$userFixtures = $container->get(UserFixtures::class);
$loader->addFixture($userFixtures);
This is package issue, can be solved by implementing ContaierAwareInterface and get dependent classes from assigned container in Loader
foreach($fixture->getDependencies() as $class) {
if (class_exists($class)) {
// $this->addFixture($this->createFixture($class));
// if fixture implements ContainerAwareInterface, load dpendencies from container
$this->addFixture($fixture->container()->get($class));
}
}
Of course we may add some additional checks like try to create class, if ArgumentCountError: error load from container. We may cache fixtures when they loaded at least once, this way if any dependent fixture requires other fixture, load it from cache, not in cache? Create, error? Load from container.
Also in ContainerAwareLoader we set container, but never use it in Loader.
Please fix it, or anyone has other solution? I dont understand why all related issues closed without solutions.
After taking another look, this looks like an issue not with this library but rather with the LiipFunctionalTestBundle not supporting dependency injection in fixtures which is provided using the Doctrine\Bundle\FixturesBundle\Loader\SymfonyFixturesLoader
and compiler passes to ensure fixture services are injected into the fixture loader.
Relevant discussion can be fixed in https://github.com/liip/LiipFunctionalTestBundle/pull/432 and https://github.com/liip/LiipFunctionalTestBundle/issues/411. This will apparently be fixed in the upcoming 2.0 release. See https://github.com/liip/LiipFunctionalTestBundle/issues/381 for relevant discussion on this.
As this is not an issue with this library or our bundle, I'm closing this issue.
@alcaeus finally it worked with SymfonyFixturesLoader, thank you very much!
Hello,
I have a project with some fixtures for functionnal testing. And one of my fixtures, for my User Entity, has a dependency injection
Thanks to symfony 4 and autowiring, it works when I use command line. Then, I wrote my functionnal test with the famous
$this->loadFixtures(array('App\DataFixtures\UserFixtures'));
At this point, I had an issue witch I solved with service_test.yaml
But now, I have more fixtures with dependencies.
And I have this error : (the same I solved with injecting in services_test.yaml)
ArgumentCountError : Too few arguments to function App\DataFixtures\UserFixtures::__construct(), 0 passed in /path/to/project/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Loader.php on line 193 and exactly 1 expected
After some breakpoints, I found this in doctrine code :
So, if my fixture implements DependentFixtureInterface it goes through createFixture method.
And I see now, it just create the fixture with new UserFixture() and no argument is passed.
So my question is :
Is this considered a bug ? Is there some kind of workaround ?
Thank you for reading.