3

私は一日中、カスタム DSL を解析して DQL クエリを作成するクラスのテストを書き込もうとしました。

私のクラスではqueryBuilder、クエリを作成して返すために使用する を渡す必要があります。

私が抱えている問題は、

  • を得るにはqueryBuilderが必要ですentityManager
  • を取得するentityManagerには、接続が必要です
  • 接続するにはデータベースが必要です

単体テストがデータベースに依存しないようにしたいので、をqueryBuilder使用してモックを作成しようとしましたPHPUnitが、接続に依存queryBuilderしているように見えentityManagerます。

2 つの質問:
Doctrine 2 でクエリを動的に構築するより良い方法はありますか? なしで(または少なくとも実際のデータベースなしで)
機能させる方法はありますか?queryBuilderentityManager

4

2 に答える 2

3

PHPUnit でそれを行う方法はわかりませんが、PHP モッキングのニーズについてMockeryを確認することをお勧めします。これは非常に強力なライブラリであり、EntityManager を非常に簡単にモックできるため、返されるものすべてをモックできます。

ユース ケースでは、モック クエリ ビルダーを返すモック エンティティ マネージャーを簡単に作成できます。

$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));
}

これは PHPUnit での推奨方法ですが、私自身はまだ試していません。

于 2013-02-08T15:11:05.997 に答える
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(),

        );
    }

}
于 2013-02-08T14:40:05.617 に答える