Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a mock object of a doctrine entity?

I'm trying to write a unit test with phpunit for a model that uses doctrine 2. I want to mock the doctrine entities but I really don't have a clue of how to do this. Can anyone explain to me how I need to do this? I'm using Zend Framework.

The model that needs to be tested

class Country extends App_Model
{
    public function findById($id)
    {
        try {
            return $this->_em->find('Entities\Country', $id);
        } catch (\Doctrine\ORM\ORMException $e) {
            return NULL;
        }
    }

    public function findByIso($iso)
    {
        try {
            return $this->_em->getRepository('Entities\Country')->findOneByIso($iso);
        } catch (\Doctrine\ORM\ORMException $e) {
            return NULL;
        }
    }
}

Bootstrap.php

protected function _initDoctrine()
{
    Some configuration of doctrine
    ... 
    // Create EntityManager
    $em = EntityManager::create($connectionOptions, $dcConf);
    Zend_Registry::set('EntityManager', $em);
}

Extended model

class App_Model
{
    // Doctrine 2.0 entity manager
    protected $_em;

    public function __construct()
    {
        $this->_em = Zend_Registry::get('EntityManager');
    }
}
like image 888
tom Avatar asked Aug 26 '10 14:08

tom


3 Answers

I have the following setUp and tearDown functions for my unit tests that use Doctrine. It gives you the ability to make doctrine calls without it actually touching the DB:

public function setUp()
{
    $this->em = $this->getMock('EntityManager', array('persist', 'flush'));
    $this->em
        ->expects($this->any())
        ->method('persist')
        ->will($this->returnValue(true));
    $this->em
        ->expects($this->any())
        ->method('flush')
        ->will($this->returnValue(true));
    $this->doctrine = $this->getMock('Doctrine', array('getEntityManager'));
    $this->doctrine
        ->expects($this->any())
        ->method('getEntityManager')
        ->will($this->returnValue($this->em));
}

public function tearDown()
{
    $this->doctrine = null;
    $this->em       = null;
}

You can then use $this->doctrine (or even) $this->em when needed. You'll need to add more method definitions should you want to use remove or getRepository.

like image 93
Jrgns Avatar answered Nov 11 '22 05:11

Jrgns


Doctrine 2 Entities should be treated like any old class. You can mock them just like any other object in PHPUnit.

$mockCountry = $this->getMock('Country');

As of PHPUnit 5.4, the method getMock() has been depricated. Use createMock() or getMockbuilder() instead.

As @beberlei noted, you are using the EntityManager inside the Entity class itself, which creates a number of sticky problems, and defeats one of the major purposes of Doctrine 2, which is that Entity's aren't concerned with their own persistance. Those 'find' methods really belong in a repository class.

like image 8
Bryan M. Avatar answered Nov 11 '22 05:11

Bryan M.


Can you show how you inject $this->_em into "Country"? It seems you mix responsibilities here by injecting the EM into an Entity. This does harm testability very much. Ideally in your models you would have business logic that is passed its dependencies, so that you don't need the EntityManager reference.

like image 1
beberlei Avatar answered Nov 11 '22 06:11

beberlei