Skip to content

Test fixtures🔗

Create fixtures🔗

Install Doctrine's fixtures bundle:

1
composer require doctrine/doctrine-fixtures-bundle

Create a fixture class:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;

class TestFixtures extends Fixture
{
    public function load(ObjectManager $manager)
    {
        $entity = new MyEntity();

        $manager->persist($entity);
        $manager->flush();
    }
}

Load fixtures🔗

The simpliest way to load fixtures in tests is liip/test-fixtures-bundle.

Install the bundle:

1
composer require liip/test-fixtures-bundle --dev

Then, in a test, use the FixturesTrait::loadFixtures() method to load your fixtures:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
use Liip\TestFixturesBundle\Test\FixturesTrait;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class AdminTest extends WebTestCase
{
    use FixturesTrait;

    public function testPages(): void
    {
        $this->loadFixtures([TestFixtures::class]);
        $client = static::createClient();

        $client->request('GET', '/');
        static::assertResponseIsSuccessful();
    }
}

Exclude table🔗

If you need to exclude table from the data purge when fixtures are reloaded, you have to use the FixturesTrait::setExcludedDoctrineTables method before loading fixtures.

You can do it directly in the test:

1
2
$this->setExcludedDoctrineTables(['messenger_messages']);
$this->loadFixtures([TestFixtures::class]);

Or extends the FixturesTrait::loadFixtures method and exclude tables in it:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
use Doctrine\Common\DataFixtures\Executor\AbstractExecutor;
use Liip\TestFixturesBundle\Test\FixturesTrait as LiipFixturesTrait;

trait FixturesTrait
{
    use LiipFixturesTrait {
        loadFixtures as liipLoadFixtures;
        loadFixtureFiles as liipLoadFixtureFiles;
    }

    protected function loadFixtures(array $classNames = [], bool $append = false, ?string $omName = null, string $registryName = 'doctrine', ?int $purgeMode = null): ?AbstractExecutor
    {
        $this->setExcludedDoctrineTables(['messenger_messages']);

        return $this->liipLoadFixtures($classNames, $append, $omName, $registryName, $purgeMode);
    }

    public function loadFixtureFiles(array $paths = [], bool $append = false, ?string $omName = null, $registryName = 'doctrine', ?int $purgeMode = null): array
    {
        $this->setExcludedDoctrineTables(['messenger_messages']);

        return $this->liipLoadFixtureFiles($paths, $append, $omName, $registryName, $purgeMode);
    }
}

Access fixtures in tests🔗

If you want to access particular fixture in a test, you can register a reference on it:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class TestFixtures extends Fixture
{
    public function load(ObjectManager $manager)
    {
        $user = new User('foobar@example.com');
        $this->setReference('foobar-user', $user);

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

Then get the reference in your test:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class AdminTest extends WebTestCase
{
    use FixturesTrait;

    public function testPages(): void
    {
        $fixtures = $this->loadFixtures([TestFixtures::class])->getReferenceRepository();
        $client = static::createClient();

        $user = $fixtures->getReference('foobar-user');

        $client->request('GET', "/admin/user/{$user->getId()}");
        static::assertResponseIsSuccessful();
    }
}

Generate fake fixtures🔗

Install Faker:

1
composer require fzaninotto/faker --dev

Then use Faker to generate fake fixtures:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class TestFixtures extends Fixture
{
    public function load(ObjectManager $manager)
    {
        $faker = \Faker\Factory::create('fr_FR');

        $user = new User($faker->email, $faker->firstName, $faker->lastName);

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

Write fixtures in YAML🔗

You can write fixtures in YAML using hautelook/alice-bundle.

You can load these YAML fixtures in tests using the loadFixtureFiles method of LiipTestFixturesBundle.

Speed up fixtures load🔗

Cache🔗

liip/test-fixtures-bundle allow you to cache fixtures in order to load fixtures from cache instead of recompute them.

See Tips for Fixture Loading Tests.

⚠️ While dumping database in cache is just copying the database file with sqlite, caching fixtures with mysql or mongodb will require dumping tools installed on the database server.

Passwords🔗

Password encoding is slow by design. Set the encoder to plaintext in test environment:

1
2
3
4
5
# config/packages/test/security.yaml
security:
    encoders:
        App\Infrastructure\Security\User\SymfonyUser:
            algorithm: plaintext

It will speed up fixtures load and password validation:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
use Liip\TestFixturesBundle\Test\FixturesTrait;

class TestFixtures extends Fixture
{
    private UserPasswordEncoderInterface $passwordEncoder;

    public function __construct(UserPasswordEncoderInterface $passwordEncoder)
    {
        $this->passwordEncoder = $passwordEncoder;
    }

    public function load(ObjectManager $manager)
    {
        $user = new User();
        $password = $this->passwordEncoder->encodePassword($user, 'password');
        $user->setPassword($password);

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

Project references🔗


Last update: December 20, 2024