0

Zend Framework アプリケーション内で PHP Unit を使用したいと考えています。テスト内でいくつかのデータベース書き込み操作を行う必要があります。setUpBeforeClass() メソッドで MySQL トランザクションを開始したいと考えています。それは可能ですが、tearDownAfterClass() メソッドでトランザクションをロールバックしようとすると、「アクティブなトランザクションがありません」というメッセージで例外がスローされます。また、テスト メソッドはデータベースへの書き込み操作を行います。しかし、テストメソッド自体でトランザクションを開始すると。それは私が望むように動作します。なぜこのように反応するのか理解できません。誰か説明を知っていますか?

<?php

class ConferenceControllerTest
extends PHPUnit_Framework_TestCase
{

    /**
     * A database connection.
     * @var Zend_Db_Adapter_Pdo_Mysql
     */
    protected static $hostDb = null;

    public static function setUpBeforeClass()
    {
        static::$hostDb = Zend_Registry::get('db_host');
        static::$hostDb->beginTransaction();
        // The transaction for the Adapter is activated. But not inside the tests anymore.
    }


    public function testTest1()
    {
        // At this position teh transaction is not setted anymor? Why?
        static::$hostDb->beginTransaction();

        $sql = 'INSERT INTO test(test) VALUES(5);';
        static::$hostDb->exec($sql);
    }

    public static function tearDownAfterClass()
    {
        try
        {
            static::$hostDb->rollBack();
        }
        catch(Exception $exception)
        {
            $message = $exception->getMessage();
            Zend_Debug::dump($message);
        }
    }

}
4

1 に答える 1

0

phpUnit の機能を実行して、各ユニット テストの間に静的データやその他のグローバル データをバックアップしている可能性があると思います。マニュアルのフィクスチャの章の「グローバル」セクションを参照してください。

クイックハック修正は、クラスのすぐ上のコメントに次の行を追加することです: * @backupStaticAttributes disabled

それでも、xUnit Patterns の本は嫌なにおいがします。前の結果に応じて、特定の順序で実行されると予想されるいくつかの testXXX 関数があると思いますか? これには、各関数で @depends を使用する必要があり、間違いやすいです。

もう 1 つのアプローチは、単一の長い単体テスト関数であり、DB コードを setUp() と tearDown() に配置します。

public function setUp()
{
    $this->db = Zend_Registry::get('db_host');
    $this->db->beginTransaction();
}

public function tearDown()
{
    try
    {
        $this->db->rollBack();
    }
    catch(Exception $exception)
    {
        $message = $exception->getMessage();
        Zend_Debug::dump($message);
    }


public function testTestVariousDBActions()
{
    $sql = 'INSERT INTO test(test) VALUES(5);';
    $this->db->exec($sql);

    //another DB action
    $this->assertEquals(...)

    //another DB action
    $this->assertEquals(...)

    //...
}

これの利点は、いずれかのアサートが失敗した場合、後続のアサートが試行されないことです。ただし、tearDown() は常に呼び出されるため、データベースは復元されます。

欠点は、非常に長い関数を取得することです。これに対処するには、リファクタリングを使用します (たとえば、各アクションとそのテストを独自の関数で本当に必要とする場合は、そのようにリファクタリングして、testTestVariousDBActions()それぞれを順番に呼び出すようにします)。

于 2012-08-24T12:26:56.777 に答える