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');
}
}
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
.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With