どのようにユニットテストは、ORMを使用するアプリで行うのですか?

StackOverflow https://stackoverflow.com/questions/673518

質問

私はユニットテストのさまざまな質問を通して見てきたが、特にこの質問に答えるものを見つけることができません。

私はこのように機能が含まれているいくつかのPHPのクラスを持ってます:

    static function _setSuspended($Suspended, $UserID)
    {
        try {
            $con = Propel::getConnection();

            $c1 = new Criteria();
            $c1->add(DomainsPeer::USERID,$UserID);

            $update = new Criteria();
            $update->add(DomainsPeer::SUSPENDED,$Suspended);

            BasePeer::doUpdate($c1, $update, $con);

            return true;
        } catch(PropelException $e) {
            return $e->getMessage();
        }
    }

私はORMとしてPropelのを使用しています。私は「モック」と「スタブ」と何ではないの作成についての話、様々なユニットテストのトピックを読んだが、私は特にあなたがどのように上記のような機能をテストするために告げる何かを見つけることができませんでした。

私はそれを呼び出すようにしたいと思うので、上記の機能をテストする必要があります。

私の考えは同じようなものです。私はそれを呼び出す場合でも、それはORMとしてPropelのを使用し、ユニットテストの原則に従って、私は自分自身で各機能を分離する必要があります。

私はちょうどそれを行うための方法が表示されません。私はここで行方不明ですか?

役に立ちましたか?

解決

私はORMの構成がテストされることは決してありませんので、ORMをからかうことは私に自信を与えていないことがわかりました。オームズもユニットテストで偽の自信を与えることができ、距離の影響で、アクションがたくさんあります。データベースドライバをからかったり、データベースが私のコードが正しいことを私もはるかに高い信頼性を提供し、ORMをからかうほど硬い程度であるインメモリの代替を提供します。

SQLiteは、ユニットテストのための優れたインメモリデータベースです。これは、PDOサポートされているデータベースのリストにあります。 (PDOはPropel 1.3データベースドライバです。)あなたは、インメモリデータベースを使用したくない場合は、すでに書かれたPDOのモックを見つけることができるかもしれない。

他のヒント

これは私がすべてではPropelに精通し、PHPでのみ多少慣れていないんだという点で、一般的な答えがあります。基本的な答えは、依存性注入を使用することです。代わりにあなたのORMを直接参照するので、あなたが実際に使用するために、あなたのクラス/関数にラッパーを注入し、その後、その周りにラッパーを作成します。ユニットテストを行うには、あなたはORMへのインターフェイスではなく、あなたのメソッド呼び出しにラッパーからの応答を設定することができますしないラッパーの模擬または偽のバージョンを作成します。これは、ユニットあなたの機能をテストするとき、あなたがORMを考慮することができます。

私はsymfonyのの PHPUnitのプラグインを構築しながら、同じ問題に取り組むためにしようとしていました。私は Djangoのテストフレームワークのと同様に、それに近づいてしまいました - 別のデータベース/接続を使用して、すべてのテストの前にそれを破壊し、再構築

私はまた、唯一のテストラン(またはテストが明示的にそれを指示した場合)での最初のテストの前にテスト・データベースを再構築して逃げることができたことがわかりました。他のテストの前に、それだけで少し物事をスピードアップするためにすべてのデータを削除します。

これは、ユニットテスト可能にすることはできませんハード依存性クラスのexempleあります。

私たちは、別のデータベースへの接続をテストすることができる可能性が、その後、それはもうユニットテストではありませんが、統合テストます。

私が考えるより良い代替はあなたが必要とするすべての異なる方法をラップし、その後、あなたはそれを模擬することができるようになりますQueryFactoryクラスを持つことです。

は、まず最初に、私は

インターフェイスを作成します
interface iQueryFactory
{
    function firstFunction($argument);
    function secondFunction($argument, $argument2);
}

私たちが必要とするすべてのあなたのORMの要求にQueryFactory

class QueryFactory implements iQueryFactory
{
    function firstFunction($argument) 
    {
        // ORM thing
    }

    function secondFunction($argument, $argument2)
    {
        // ORM stuff
    }
}

クエリ工場の注入とのビジネスlogiqueがあります。

class BusinessLogic 
{
    protected $queryFactory;

    function __construct($queryFactoryInjection) 
    {
        $this->queryFactory= $queryFactoryInjection;
    }

    function yourFunctionInYourBusinessLogique($argument, $argument2) 
    {
        // business logique

        try {
            $this->queryFactory->secondFunction($argument, $argument2);
        } catch (\Exception $e) {
            // log
            // return thing
        }

        // return stuff
    }
}

モックの部分、私は私のexempleのモックフレームワークを使用していないことに注意してください(ところで、あなたが応答セッターを作成することができます)。

class QueryFactoryMock implements iQueryFactory
{
    function firstFunction($argument) 
    {
        if (is_null($argument)) 
        {
            throw new \Exception("");
        } 
        else 
        {
            return "succes";
        }
    }

    function firstFunction($argument, $argument2) 
    { 
        // sutff  
    }
}

そして、最終的にはモック実装で、当社のビジネスロジックをテストするユニットテスト

class BusinessLogicTest extends PHPUnit_Framework_TestCase 
{
    public function setUp() 
    {
        require_once "BusinessLogic.php";
    }

    public function testFirstFunction_WhenInsertGoodName() 
    {
        $queryMockup = new QueryFactoryMock();
        $businessLogicObject = new BusinessLogic($queryMockup);
        $response = $businessLogicObject ->firstFunction("fabien");

        $this->assertEquals($response, "succes");
    }

    public function testFirstFunction_WhenInsetNull() 
    {
        $queryMockup = new QueryFactoryMock();
        $businessLogicObject = new BusinessLogic($queryMockup);
        $response = $businessLogicObject->firstFunction(null);

        $this->assertEquals($response, "fail");
    }
}
scroll top