Как создать макет объекта сущности доктрины?
Я пытаюсь написать unit test с phpunit для модели, использующей доктрину 2. Я хочу издеваться над сущностями доктрины, но я действительно не знаю, как это сделать. Может ли кто-нибудь объяснить мне, как мне это нужно? Я использую Zend Framework.
Модель, которая должна быть протестирована
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);
}
Расширенная модель
class App_Model
{
// Doctrine 2.0 entity manager
protected $_em;
public function __construct()
{
$this->_em = Zend_Registry::get('EntityManager');
}
}
Ответы
Ответ 1
Doctrine 2 Entities следует рассматривать как любой старый класс. Вы можете издеваться над ними, как и любой другой объект в PHPUnit.
$mockCountry = $this->getMock('Country');
Как и в PHPUnit 5.4, метод getMock() был лишен. Вместо этого используйте createMock() или getMockbuilder().
Как отметил @beberlei, вы используете EntityManager внутри самого класса Entity, что создает ряд липких проблем и побеждает одну из основных целей Doctrine 2, которая заключается в том, что Entity не связаны с их собственным сопротивлением, Эти методы поиска действительно принадлежат классу репозитория .
Ответ 2
У меня есть следующие функции setUp и tearDown для моих модульных тестов, которые используют Doctrine. Это дает вам возможность совершать вызовы доктрины без фактического касания БД:
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;
}
Затем вы можете использовать $this->doctrine
(или даже) $this->em
при необходимости. Вам нужно будет добавить дополнительные определения методов, если вы хотите использовать remove
или getRepository
.
Ответ 3
Можете ли вы показать, как вы введете $this → _ em в "Страна"? Кажется, вы смешиваете обязанности здесь, вводя EM в Entity. Это очень важно. В идеале в ваших моделях у вас будет бизнес-логика, которая передает свои зависимости, так что вам не нужна ссылка EntityManager.