2012-08-23 42 views
0

我想在Zend Framework应用程序中使用PHP单元。我需要在测试中进行多个数据库写入操作。 我想在setUpBeforeClass()方法中启动一个MySQL事务。这是可能的,但如果我尝试在tearDownAfterClass()方法中回滚事务,他会抛出一个异常,并显示消息'There no no active transaction'。测试方法在数据库中执行写入操作。 但是,如果我在测试方法本身开始交易。它像我想要的那样工作。 我不明白为什么它会这样反应。知道任何人的解释?Zend Framework,PHPUnit和交易

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

} 

回答

0

我想你可能会运行到PHPUnit的功能,备份静态和每个单元测试之间的其他全局,看到the "globals" section of the Fixtures chapter of the manual

的快速破解补丁将加入这一行,在评论上方您的班级: * @backupStaticAttributes已禁用

这仍然给您留下xUnit Patterns书会引起讨厌的气味。我假设你有几个testXXX函数,你希望按照一定的顺序运行,每个函数都取决于前一个的结果?这需要在每个函数上使用@depends,并且很容易出错。

的另一种方法是一个长单元测试功能,并把在设置())的DB代码和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()将始终被调用,以便恢复数据库。

缺点可能是你得到一个非常长的功能。使用重构来处理这个问题(例如,如果你真的希望每个动作和它的测试都在它自己的函数中进行重构,那么看起来就像这样并且依次调用它们中的每一个)。