Welcome to Abdul Malik Ikhsan's Blog

Using Doctrine Data Fixture for Testing QueryBuilder inside Repository

Posted in Tutorial PHP by samsonasik on March 24, 2015

Doctrine This is an immediate post to incorporate my latest post about Mocking Doctrine\ORM\AbstractQuery to test querybuilder. Well, while that works, Ocramius – A Doctrine core team – said that we shouldn’t do that way, as SQL and DQL are actual code. What we can do is using data fixture. There is a sample that he gave with ZF2 environment. In this post, I will try to write a demo with step by step about repository class that consume a QueryBuilder, so we can test it.

Let’s start with the Entity

Like my post before, I will going to use News entity :

namespace DoctrineFixtureDemo\Entity;

use Doctrine\ORM\Mapping as ORM;

 * News
 * @ORM\Table(name="news")
 * @ORM\Entity(repositoryClass="DoctrineFixtureDemo\Repository\NewsRepository")
class News
     * @var integer
     * @ORM\Column(name="id", type="bigint", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
    private $id;

     * @var string
     * @ORM\Column(name="title", type="string", length=50, nullable=false)
    private $title;

     * @var string
     * @ORM\Column(name="content", type="string", length=255, nullable=false)
    private $content;

     * Get id.
     * @return integer
    public function getId()
        return $this->id;

     * Set title.
     * @param string $title
     * @return self
    public function setTitle($title)
        $this->title = $title;

        return $this;

     * Get title.
     * @return string
    public function getTitle()
        return $this->title;

     * Set content.
     * @param string $content
     * @return self
    public function setContent($content)
        $this->content = $content;

        return $this;

     * Get content.
     * @return string
    public function getContent()
        return $this->content;

The Repository

I have a repository to get latest news with limit parameter, like the following :

namespace DoctrineFixtureDemo\Repository;

use Doctrine\ORM\EntityRepository;

class NewsRepository extends EntityRepository
     * Get Latest News.
     * @param int $limit
     * @return array
    public function getLatestNews($limit)
        $result = $this->createQueryBuilder('n')

        return $result;

Fixture Dependency

We need "doctrine/data-fixtures" dependency in our vendor/, we can require by composer command :

$ composer require "doctrine/data-fixtures 1.0.*"

Fixture Class

We can create a fixture class to insert some sample data to be tested.

namespace DoctrineFixtureDemo\DataFixture;

use DoctrineFixtureDemo\Entity\News;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\DataFixtures\FixtureInterface;

class NewsLoad implements FixtureInterface
    public function load(ObjectManager $manager)
        $news = new News();

        $news2 = new News();


We are going to use Doctrine\Common\DataFixtures\Executor\ORMExecutor to execute loaded fixture class(es). We can setup fixture test by use database that only for test / not for production ( – note : this is just sample, you can rely on your framework for get the db setting, EntityManager, SchemaTool, etc – ) by creating class like the following :

namespace DoctrineFixtureDemotest;

use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\AnnotationRegistry;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
use Doctrine\ORM\Tools\SchemaTool;

final class FixtureManager
     * Get EntityManager
    public static function getEntityManager()
        $paths = [dirname(__DIR__).'/src/DoctrineFixtureDemo/Entity'];
        $isDevMode = true;

        // the TEST DB connection configuration
        $connectionParams = [
            'driver'   => 'pdo_mysql',
            'user'     => 'root',
            'password' => '',
            'dbname'   => 'foobartest',

        $config = Setup::createConfiguration($isDevMode);
        $driver = new AnnotationDriver(new AnnotationReader(), $paths);


        $entityManager = EntityManager::create($connectionParams, $config);

        return $entityManager;
     * Make sure drop and create tables
    public static function start()
        $schemaTool = new SchemaTool(static::getEntityManager());
        $metadatas  = static::getEntityManager()


     * @return ORMExecutor
    public static function getFixtureExecutor()
        return new ORMExecutor(
            new ORMPurger(static::getEntityManager())

In favor of above class, we can always call \DoctrineFixtureDemotest\FixtureManager::start(); at our phpunit’s bootstrap :


$loader = null;
if (file_exists('../vendor/autoload.php')) {
    $loader = include '../vendor/autoload.php';
} else {
    throw new RuntimeException('vendor/autoload.php could not be found. Did you run `php composer.phar install`?');

$loader->add('DoctrineFixtureDemotest', __DIR__);

So, all tables will be removed in the every beginning test.

Repository Test

Time for test, Our repository class test can be like the following :

namespace DoctrineFixtureDemoTest\Repository;

use DoctrineFixtureDemo\DataFixture\NewsLoad;
use DoctrineFixtureDemotest\FixtureManager;
use DoctrineFixtureDemo\Repository\NewsRepository;
use Doctrine\ORM\Mapping\ClassMetadata;
use PHPUnit_Framework_TestCase;

class NewsRepositoryTest extends PHPUnit_Framework_TestCase
    protected function setUp()
        $this->repository      = new NewsRepository(
            new ClassMetadata('DoctrineFixtureDemo\Entity\News')

        $this->fixtureExecutor = FixtureManager::getFixtureExecutor();

    public function testGetLatestNews()
        $this->fixtureExecutor->execute([new NewsLoad()]);
        $this->assertCount(1, $this->repository->getLatestNews(1));
        $this->assertInstanceOf('DoctrineFixtureDemo\Entity\News', $this->repository->getLatestNews(1)[0]); 

If everything goes well, then your repository class will be tested.

Want to grab the sourcecode?, you can take a look https://github.com/samsonasik/DoctrineFixtureDemo

Another approach

You can already have prepared tables before test executed, and call truncate in every tearDown() at your unit test class as Manuel Stosic suggestion.

References :
1. https://twitter.com/Ocramius/status/577979551281729536
2. https://github.com/doctrine/data-fixtures
3. https://gist.github.com/Ocramius/3994325


10 Responses

Subscribe to comments with RSS.

  1. […] Ocramius suggest to not do it. He suggest to use Fixture instead like his gist. I created a new post in favor of […]

  2. Sam said, on March 24, 2015 at 2:19 pm

    $result = $this->_em->getRepository($this->getEntityName())
    $result = $this
    You’re already inside the repository, so no need to get the repository ^^ Other than that, good quick overview on how to set up Fixtures quickly.

    One hint though: I’d always run a TRUNCATE TABLE on the UnitTests tearDown() so I can be absolutely certain that other tests won’t have problems. Every test case should load it’s own fixture ultimately.

  3. Alejandro Celaya said, on March 24, 2015 at 2:42 pm

    Good approach!

    By the way, doing this inside a repository class $this->_em->getRepository($this->getEntityName()) won’t be the same as $this? ๐Ÿ˜‰

  4. David Mintz said, on October 14, 2015 at 9:46 pm

    Just want to say thank you. This is still some dark magic to me, but I will keep staring and blinking, poking and prodding, following along in a monkey-see-monkey-do fashion until I begin to really understand all the wiring.

    Right now I’ve been attempting to combine the simple bootstrap.php provided in your repo with the more elaborate Bootstrap.php suggested at http://framework.zend.com/manual/current/en/tutorials/unittesting.html, so we can run one phpunit command using a single bootstrap for all the tests in a ZF module, i.e., testing both controllers and entities. I seem to have a crude solution but maybe will return with another comment if I come up with something useful.

  5. Jani said, on February 15, 2016 at 8:07 pm

    Thank you! This was exactly what I was looking for!

  6. David Mintz said, on April 29, 2016 at 10:07 pm

    I am following this recipe, but extending Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase. In my setup(), I am doing like so:

    $fixtureExecutor = FixtureManager::getFixtureExecutor();

    new DataFixture\JudgeLoader,
    new DataFixture\UserLoader,
    new DataFixture\LanguageLoader,
    new DataFixture\EventTypeLoader,
    new DataFixture\DefendantNameLoader,
    new DataFixture\RequestLoader,

    include ‘config/application.config.php’
    /* etc */

    These entities have various relationships to one another, e.g., many-to-one, and I need them all in order to to test certain controller actions.

    In my service manager configuration I am setting up Doctrine’s FileSystemCache to reduce the database queries. In my “development” environment I am using MySQL and it’s working great, as best I can tell. But in my “testing” environment I am using SQLite, because it’s been recommended and I thought its speed would be an advantage. And there, I am getting “PDOException: SQLSTATE[HY000]: General error: 5 database is locked” timeout errors whenever the cache is enabled. If I disable it, all goes smoothly.

    Any idea what I might be doing wrong here?

    • samsonasik said, on April 30, 2016 at 1:03 am

      I’ve no idea, sorry. My suggestion is, if your app is using MySQL, just use MySQL as well for testing so you get “test real app db”.

      • David Mintz said, on April 30, 2016 at 8:32 am

        thanks for replying. you know what? I wanted to withdraw this comment before it was too late ๐Ÿ™‚ . It was one of those things where the symptoms of the problem seemed so remote from the cause that it’s no wonder I had a hard time figuring it out. it turns out it was related to the way I was initializing sqlite and adding a user-defined function. it appeared to be working, but not because I was doing it right but because I was lucky. when I added caching to the mix, my luck ran out and my unit tests crashed and burned. i figured out the right way to do it by reading the source code. but i won’t go into detail — the whole issue is off-topic with respect to your excellent blog post here, so I won’t be offended if you remove this little comment thread. thanks again!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: