我正在尝试使用phpunit为使用doctrine 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');
}
}
答案 0 :(得分:15)
对于使用Doctrine的单元测试,我有以下setUp和tearDown函数。它使您能够在没有实际接触数据库的情况下进行学说调用:
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
,则需要添加更多方法定义。
答案 1 :(得分:8)
原则2实体应该像任何旧类一样对待。您可以像PHPUnit中的任何其他对象一样模拟它们。
$mockCountry = $this->getMock('Country');
从PHPUnit 5.4开始,方法getMock()已被删除。改为使用createMock()或getMockbuilder()。
正如@beberlei所指出的那样,你在Entity类中使用EntityManager,这会产生许多棘手问题,并且会破坏Doctrine 2的主要目的之一,即Entity并不关心它们自身的持久性。那些“查找”方法确实属于repository class。
答案 2 :(得分:1)
你能说明你如何将$ this-> _em注入“国家”吗?看来你通过将EM注入实体来混合职责。这极大地损害了可测试性。理想情况下,在模型中,您将拥有传递其依赖项的业务逻辑,因此您不需要EntityManager引用。