Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InvalidArgumentException: "App\DataFixtures\UserFixtures" is not a registered fixture #64

Closed
dubitoph opened this issue Apr 29, 2020 · 12 comments

Comments

@dubitoph
Copy link

dubitoph commented Apr 29, 2020

I'm using Symfony 5. I installed "LiipTestFixturesBundle" with composer require --dev liip/test-fixtures-bundle.

I created this fixture :

<?php

namespace App\DataFixtures;

use App\Entity\user\User;
use App\Entity\user\Profile;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

class UserFixtures extends AbstractFixture implements FixtureInterface
{
 
    private $encoder;
 
    public function __construct(UserPasswordEncoderInterface $encoder)
    {

        $this->encoder = $encoder;

    }
    public function load(ObjectManager $manager)
    {

        for($i = 0; $i < 10; $i++) 
        {

            $user = new User();
            $profile = new Profile();
            $hash = $this->encoder->encodePassword($user, 'roadtripr12');

            $user
                ->setName('username' . $i)
                ->setFirstname('firstname' . $i)
                ->setEmail('username' . $i . '@roadtripr.com')
                ->setRoles(['ROLE_USER'])
                ->setPassword($hash)
                ->setUserName('username' . $i)
                ->setProfile($profile)
            ;

        }

        for($i = 0; $i < 10; $i++) 
        {

            $user = new User();
            $profile = new Profile();
            $hash = $this->encoder->encodePassword($user, 'roadtripr12');

            $user
                ->setName('ownerUsername' . $i)
                ->setFirstname('ownerFirstname' . $i)
                ->setEmail('ownerUsername' . $i . '@roadtripr.com')
                ->setRoles(["ROLE_OWNER","ROLE_USER"])
                ->setPassword($hash)
                ->setUserName('ownerUsername' . $i)
                ->setProfile($profile)
            ;

        }

        for($i = 0; $i < 5; $i++) 
        {

            $user = new User();
            $profile = new Profile();
            $hash = $this->encoder->encodePassword($user, 'roadtripr12');

            $user
                ->setName('adminrUsername' . $i)
                ->setFirstname('adminFirstname' . $i)
                ->setEmail('ownerUsername' . $i . '@roadtripr.com')
                ->setRoles(["ROLE_ADMIN","ROLE_USER"])
                ->setPassword($hash)
                ->setUserName('adminUsername' . $i)
                ->setProfile($profile)
            ;

        }

    }

}

I created this test :

<?php

namespace App\tests\Repository\user;

use App\DataFixtures\UserFixtures;
use App\Repository\user\UserRepository;
use Liip\TestFixturesBundle\Test\FixturesTrait;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class UserRepositoryTest extends WebTestCase
{

    use FixturesTrait;

    public function testCount()
    {

        self::bootKernel();
        $this->loadFixtures(array(UserFixtures::class));

        $users = self::$container->get(UserRepository::class)->count([]);

        $this->assertEquals(25, $users);

    }
    
}

When I run php bin/phpunit, I have this error :

InvalidArgumentException: "App\DataFixtures\UserFixtures" is not a registered fixture

@alexislefebvre
Copy link
Collaborator

Please try these suggestions: #57 (comment)

@dubitoph
Copy link
Author

dubitoph commented Apr 30, 2020

Hello, I don't understand what I must try because my fixtures are in the src/Datafixtures repository.

@dubitoph
Copy link
Author

dubitoph commented Apr 30, 2020

In the fixture, I changed the Doctrine\Common\DataFixtures\FixtureInterface implementation to Doctrine\Common\DataFixtures\AbstractFixture implementation. I don't have anymore the previously error, but the data aren't saved in the database.

@alexislefebvre
Copy link
Collaborator

alexislefebvre commented Apr 30, 2020

You need to persist data: https://symfony.com/doc/3.0/bundles/DoctrineFixturesBundle/index.html#writing-fixtures

Add this for every entity:

$manager->persist($user);
$manager->flush();

@dubitoph
Copy link
Author

Of course! Really sorry for this mistake on my part and thank you very much for your help.

@vulkanosaure
Copy link

vulkanosaure commented Nov 7, 2023

Add this for every entity:
$manager->persist($user);
$manager->flush();

are you saying that we need to flush inside the loop ?
flush is designed to be called only once at the end, or isn't that what you meant ?

edit : I also saw an article where someone was flushing in the loop, so I'm really curious if there is something i don't know about.
I don't wanna do it unless it's really necessary since that sounds like a waste of resource.

@alexislefebvre
Copy link
Collaborator

alexislefebvre commented Nov 7, 2023

@vulkanosaure you can call flush() only once, it should work.

If you add tens or hundreds of entities, check the doc about Batch Processing: https://www.doctrine-project.org/projects/doctrine-orm/en/2.16/reference/batch-processing.html

See also this answer on Stack Overflow: https://stackoverflow.com/a/21335487/2257664 (spoiler: it's mine 😁)

@vulkanosaure
Copy link

thanks but why isn't using one single flush for a hundred of entities recommended ?
is it slower than the batch process you describe ? (eg: 10 flush that each handle 10 persist)

@alexislefebvre
Copy link
Collaborator

alexislefebvre commented Nov 8, 2023

Adding hundreds of records then:

  • using only flush at the end may use a lot of RAM (hydrated entities can be pretty heavy). If I remember correctly Doctrine had performance issues when dealing with thousand of entities and the final flush was slow. It was about 10 years ago though so it may be better now
  • using flush on every iteration of the loop may be slower since it will perform many requests

Between these 2 cases, batch processing is a trade-off and it can help to not overwhelm Doctrine. It depends on the amount of data to be stored, so the first step is to test and see if you encounter performance issues, if that's the case then you can try different sizes for the batch. If you have no slowness when adding entities, keep one flush and move along.

@vulkanosaure
Copy link

ok, thanks for the insights !

@vulkanosaure
Copy link

vulkanosaure commented Nov 10, 2023 via email

@alexislefebvre
Copy link
Collaborator

@vulkanosaure Let's discuss this there:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants