0

我想在 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);
        }
    }

}
4

1 回答 1

0

我认为您可能会遇到 phpUnit 的功能,即在每个单元测试之间备份静态和其他全局变量,请参阅手册的 Fixtures 章节的“全局变量”部分

快速破解方法是在您班级上方的评论中添加这一行:* @backupStaticAttributes disabled

这仍然给您留下了 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()依次调用它们)。

于 2012-08-24T12:26:56.777 回答