我一直在努力为一个解析自定义DSL并创建DQL查询的类编写一些测试。
我的班级要求我传入一个queryBuilder
,然后用它来构建查询并将其返回。
我遇到的问题是
queryBuilder
我需要entityManager
entityManager
我需要连接我宁愿我的单元测试不依赖于数据库所以我一直在尝试使用queryBuilder
创建模拟PHPUnit
,但queryBuilder
似乎依赖于entityManager
反过来依赖于连接。
所以2个问题:
有没有更好的方法在Doctrine 2中动态构建查询?
有没有办法让queryBuilder
没有entityManager
(或者至少没有真正的数据库)?
答案 0 :(得分:3)
我不确定如何使用PHPUnit,但我建议您查看Mockery以了解PHP模拟需求。它是一个非常强大的库,它允许您非常轻松地模拟EntityManager,因此它将返回任何内容。
对于您的用例,您可以轻松创建Mock实体管理器,而不是返回模拟查询构建器:
$mockEm = \Mockery::mock('\Doctrine\ORM\EntityManager');
$mockQb = \Mockery::mock('\Doctrine\ORM\QueryBuilder');
$mockEm->shouldReceive('createQueryBuilder')->andReturn($mockQb);
然后,您可以使用Mockery的核心功能来设置单元测试所需的期望。
稍微提一下,您还可以选择使用“被动”EntityManager模拟器,以防您想要对包含某些数据库逻辑的函数进行单元测试,但实际上并不想进入数据库你的单元测试。
public function getPassiveEntityManagerMock() {
return \Mockery::mock('\Doctrine\ORM\EntityManager',
array('getRepository' => new FakeRepository(),
'getClassMetadata' => (object)array('name' => 'aClass'),
'persist' => null,
'flush' => null));
}
Here's建议使用PHPUnit的方法,但我自己没有尝试过。
答案 1 :(得分:1)
我最终创建了自己的模拟查询构建器;可能有可能使用PHPUnits模拟框架获得相同的功能,但这是我最终得到的结果:
<?php
namespace MyNameSpace\Tests\Mocks;
use Doctrine\ORM\QueryBuilder;
use Doctrine\Common\Collections\ArrayCollection;
class MockQueryBuilder extends QueryBuilder {
protected $expr;
protected $paramReflect;
public function __construct($expr) {
$this->expr = $expr;
$this->paramReflect = new \ReflectionProperty('Doctrine\ORM\QueryBuilder', 'parameters');
$this->paramReflect->setAccessible(true);
$this->paramReflect->setValue($this, new ArrayCollection());
}
/*
* @return Query\Expr
*/
public function expr() {
return $this->expr;
}
public function getEntityManager() {
return null;
}
public function getQuery() {
return array(
'parameters' => clone $this->paramReflect->getValue($this),
'dql' => $this->getDQL(),
);
}
}