获取模拟Doctrine \ ORM \ QueryBuilder

时间:2013-01-31 16:36:20

标签: php symfony doctrine-orm mocking phpunit

我一直在努力为一个解析自定义DSL并创建DQL查询的类编写一些测试。

我的班级要求我传入一个queryBuilder,然后用它来构建查询并将其返回。

我遇到的问题是

  • 获得queryBuilder我需要entityManager
  • 获得entityManager我需要连接
  • 获取连接我需要一个数据库

我宁愿我的单元测试不依赖于数据库所以我一直在尝试使用queryBuilder创建模拟PHPUnit,但queryBuilder似乎依赖于entityManager反过来依赖于连接。

所以2个问题:
有没有更好的方法在Doctrine 2中动态构建查询?
有没有办法让queryBuilder没有entityManager(或者至少没有真正的数据库)?

2 个答案:

答案 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(),

        );
    }

}