Symfony. Improving your tests with DoctrineFixturesBundle
Create fake data for your tests with the DoctrineFixturesBundle bundle
One of the most tedious things we have to face when we write the tests of our application is the generation of test data.
For example, suppose we want to write the tests related to the web blog we are developing. In order to perform certain tests, we probably need that in the database there are already entities created so that we can navigate through them or test the different actions associated with them.
The simplest option we have for this is to directly create that data from our Test
class, something that in the long run is not maintainable, because we would end up with a large amount of repeated code (at the moment we have several dependent entities, one of the others) and that would “dirty” the class itself.
This is where DoctrineFixturesBundle appears, which will greatly simplify this whole process. Lets go see it!
Installation
As I commented in the introduction of the article, DoctrineFixturesBundle allows the insertion of test data into our database in order to perform tests or other actions. In addition, it is compatible with any database with which it is Doctrine (MySQL, SQLite …)
To install this bundle in our project (assuming you are using version 4 of Symfony) we will use composer
:
composer require --dev orm-fixtures
Whose recipe
will perform the rest of the actions necessary to leave the bundle configured, although it never hurts to make sure that the following line has been added to our bundles.php
file:
Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true]
Writing our first Fixture
Once the bundle is installed, the DataFixtures
folder will be added to our src
folder, which is where we will create the classes for our Fixtures.
To create a Fixture
class, all we need is to create it in the DataFixtures
folder and extend the Fixture
class provided by the bundle.
For example, suppose that as I said at the beginning we need to write the tests of a blog. What we will do is generate the PostFixtures
class:

As you can see the code is quite simple. Within the load
method belonging to the Doctrine\Bundle\FixturesBundle\Fixture
class, what we will do is create 20 Post
entities and execute the EntityManager flush
method as we normally would.
Now, to load this data into a database, we will execute the following instruction from the command line:
bin/console doctrine:fixtures:load
and we are ready! We already have 20 test articles to perform our tests.
👁️! When executing that command the database is “purged”, so if you want to just add such data you must add the “append” option.
If you are wondering what the command does, the answer is very simple. Thanks to the autoconfigure
option, Symfony is able to label the declared classes as services (which by default are all but those found in the Entity folders) depending on the interface they implement. In our case, since we are inheriting from Fixture
, this abstract class implements the ORMFixtureInterface
interface, so all the classes that inherit from it will be cataloged as Fixtures
and therefore loaded by means of the previous command.
How to create dependent Fixtures
Before moving on to see how we can use Fixtures in our tests, I would like to talk about how we can create Fixtures that depend on others.
Returning to our example, it could be that each article belonged to a category, so we would also have to create a few categories in our test data.
Although we could generate these categories within the PostFixtures
class itself, the most appropriate solution is to implement the DependentFixturesInterface
interface so that we can relate some fixtures to others. Let’s see how to do it.
The first thing we will do is create our PostCategoryFixtures.php
class:

Since PostCategoryFixtures
we will use it later as a dependency of PostCategory
, the code is somewhat different from that of the previous Fixture:
- On line 21 I am using
addReference
to tell the bundle to add a reference to the Doctrine$category
object so that it can be searched later. This method receives two arguments, the key to save the reference to the object and the object itself. - On line 11, I am creating a static method of home-grown in order to generate references for the objects created by Fixture based on the index of the loop.
Once this is done, we will modify our PostFixtures
file to add the following:

The modifications are as follows:
- On lines 9 and 11 this is importing the
DependentFixtureInterface
interface and implementing it. - On line 16 I am using the
getReference
method of theFixture
abstract class to retrieve a reference to an object in previously stored Doctrine. For this I need the object key, which I generate with the static methodgetReferenceKey
of thePostCategoryFixtures
class to which I pass an index between 0 and 4 (since I have only created 5 categories). - On line 30 I declare the dependencies of this Fixture, so that when loaded by means of the
doctrine:fixtures:load
command, the Fixtures indicated as dependencies are also executed.
Thanks to this, we can already generate test articles along with their relevant categories.
How to access services within a Fixture
Another of the situations that may arise when we are generating Fixtures is having to use a service, for example, if we are creating test users, we need to access the UserPasswordEncoderInterface
service to encrypt their passwords.
This however is very easy to solve because all our Fixtures are (unless you have specified otherwise in the services.yaml
file) services, so that we can inject dependencies in the usual way through the constructor:
public function __construct(UserPasswordEncoderInterface $encoder)
{
$this->encoder = $encoder;
}
Still, and in extreme cases we have two alternative solutions.
The first is to access the $this->container
property of the Fixture itself but that has the limitation of not being able to return those services that we have declared as private.
The second is to implement the Symfony\Component\DependencyInjection\ContainerAwareInterface
interface and use the Symfony\Component\DependencyInjection\ContainerAwareTrait
trait within the fixture so that we also have access to $this->container
.
Integrating fixtures with PHPUnit
Once we are familiar with the way we can create Fixtures, it is time to integrate the bundle with PHPUnit because, at the moment, to add our Fixtures to the database it is necessary to execute the command:
bin/console doctrine:fixtures:load
This causes that every time we run our tests we have to make sure that the Fixtures have been loaded, something that is very easy for us to ignore. Ideally, each test will be responsible for loading the Fixtures database with which it will work for which there are two alternatives.
LiipTestFixturesBundle
The LiipTestFixturesBundle bundle was originally integrated into the LiipFunctionalTestBundle bundle which adds a number of very interesting features to the PHPUnit suite such as running parallel tests or creating authenticated clients for end-to-end tests. However, as of version 3.0 the functionality of loading fixtures was separated to a separate bundle.
We will install it through composer:
composer require --dev liip/test-fixtures-bundle:^1.0.0
This will allow us to add the Liip\TestFixturesBundle\Test\FixturesTrait
trait to our test classes. Thus, in each method that defines a test we can use the loadFixtures
method to specify which Fixtures we want to load when that test is to be executed:
use Liip\TestFixturesBundle\Test\FixturesTrait;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class MyControllerTest extends WebTestCase
{
use FixturesTrait;
public function testIndex()
{
// add all your fixtures classes that implement
// Doctrine\Common\DataFixtures\FixtureInterface
$this->loadFixtures(array(
'App\DataFixtures\PostFixtures',
'App\DataFixtures\ProjectFixtures'
));
...
In addition, this bundle presents some interesting functionality such as the possibility of excluding some tables from being purged when the fixtures are loaded or the option of adding the fixtures to the tables instead of having them previously purged.
Other solution
On the other hand, if you prefer not to resort to a third-party bundle you can always create the following class in your project:

This abstract class provides the addFixture
method to the classes that extend it to add the Fixtures that we want to execute and the executeFixtures
method to execute the Fixtures thus added. For example:
class DeletePostControllerTest extends AuthenticatedClientWebTestCase {protected function setUp() { $kernel = self::bootKernel(); $this->addFixture(new PostFixtures()); $this->executeFixtures();}
The only “but” in this way is that we must instantiate the Fixtures classes before passing them to the addFixture
method (in our example new PostFixtures()
) which causes that if we need to inject dependencies it is we who have to do it.
In summary…
As you can see, DoctrineFixturesBundle makes it very easy for us to write tests, also centralizing the creation of test data in one place. In addition, we can use this bundle to fill the database so that we can show how the application would look once there was data in it, something that is very useful in customer presentations.
I hope you liked the article. See you in the following!
¿Quieres recibir más artículos como este?
Si te ha gustado este artículo te animo a que te suscribas a la newsletter que envío cada domingo con publicaciones similares a esta y más contenido recomendado: 👇👇👇