2013-01-31 44 views
2

我一直在嘗試爲解析自定義DSL並創建DQL查詢的類編寫一些測試。獲取模擬原理 ORM QueryBuilder

我的課程要求我傳入一個queryBuilder,然後使用它構建查詢並將其返回。

我的問題是,

  • 獲得queryBuilder我需要一個entityManager
  • 得到一個entityManager我需要一個連接
  • 得到我需要一個數據庫的連接

我寧願我的單元測試不依賴於數據庫,所以我一直試圖創建一個模擬queryBuilder使用PHPUnit,但queryBuilder似乎依賴於entityManager,而這又依賴於連接。

所以有2個問題:
有沒有更好的方法來動態構建在Doctrine 2中的查詢?
有沒有辦法得到一個工作queryBuilder沒有entityManager(或至少沒有一個真正的數據庫)?

+0

如果您使用MockBuilder模擬QueryBuilder並調用disableOriginalConstructor方法 - 那麼您不需要任何實體管理器。如果你發佈你想要測試的課程,這將更容易回答你的問題 – Cyprian

回答

1

我最終創建了自己的模擬查詢生成器;它可能已被使用可能嘲諷PHPUnits框架,以獲得相同的功能,但是這是我最後WHA了:

<?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(), 

     ); 
    } 

} 
2

我不知道如何使用PHPUnit做到這一點,但我會建議對檢查出Mockery你的PHP嘲笑需求。這是一個非常強大的庫,它允許你很容易地模擬EntityManager,因此它會返回任何東西。

對於你的使用情況,您可以輕鬆創建一個模擬實體管理器比將返回一個模擬查詢生成器:

$mockEm = \Mockery::mock('\Doctrine\ORM\EntityManager'); 
$mockQb = \Mockery::mock('\Doctrine\ORM\QueryBuilder'); 
$mockEm->shouldReceive('createQueryBuilder')->andReturn($mockQb); 

然後你可以用嘲弄的核心功能來設定您所需要的預期你的單元測試。

在略有不同的情況下,您還可以選擇使用'被動'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的做這件事的建議的方式,但我還沒有嘗試過了自己。