【问题标题】:Zend Framework, PHPUnit and transactionsZend 框架、PHPUnit 和事务
【发布时间】:2012-08-19 07:21:53
【问题描述】:

我想在 Zend Framework 应用程序中使用 PHP 单元。我需要在测试中进行几个数据库写入操作。 我想在 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);
        }
    }

}

【问题讨论】:

    标签: php mysql zend-framework transactions phpunit


    【解决方案1】:

    我认为您可能会遇到 phpUnit 的功能,即在每个单元测试之间备份静态和其他全局变量,请参阅 the "globals" section of the Fixtures chapter of the manual

    快速破解方法是在您班级上方的 cmets 中添加这一行: * @backupStaticAttributes 禁用

    这仍然给您留下了 xUnit Patterns 书,这本书会被称为难闻的气味。我假设您有一些 testXXX 函数,您希望以特定顺序运行,每个函数都取决于前一个函数的结果?这需要对每个函数都使用@depends,很容易出错。

    另一种方法是单个长单元测试函数,并将 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() 依次调用它们中的每一个)。

    【讨论】:

      猜你喜欢
      • 2013-05-22
      • 2011-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-03
      • 2013-04-20
      • 1970-01-01
      • 2011-12-23
      相关资源
      最近更新 更多