【问题标题】:PHPUnit and MySQL truncation errorPHPUnit 和 MySQL 截断错误
【发布时间】:2012-04-26 10:16:48
【问题描述】:

我对 PHPUnit 在插入夹具之前总是运行 TRUNCATE 的行为感到头疼没有首先设置外键检查:

Syntax error or access violation: 1701 Cannot truncate a table referenced in a foreign key constraint

基本上,PHPUnit 会在插入固定装置之前尝试截断表格。如何告诉SET FOREIGN_KEY_CHECKS=0;

【问题讨论】:

  • 即使引用您要截断的表的表为空,也会发生这种情况。很确定这是一个 MySQL 错误,不管这里的 cmets:bugs.mysql.com/bug.php?id=54678@Tower 解决方案遗憾的是唯一的选择。

标签: php mysql phpunit


【解决方案1】:

我似乎找到了答案。我最终通过扩展一个类来覆盖一些方法。

<?php

/**
 * Disables foreign key checks temporarily.
 */
class TruncateOperation extends \PHPUnit_Extensions_Database_Operation_Truncate
{
    public function execute(\PHPUnit_Extensions_Database_DB_IDatabaseConnection $connection, \PHPUnit_Extensions_Database_DataSet_IDataSet $dataSet)
    {
        $connection->getConnection()->query("SET foreign_key_checks = 0");
        parent::execute($connection, $dataSet);
        $connection->getConnection()->query("SET foreign_key_checks = 1");
    }
}

然后示例用法:

class FooTest extends \PHPUnit_Extensions_Database_TestCase
{
    public function getSetUpOperation()
    {
        $cascadeTruncates = true; // If you want cascading truncates, false otherwise. If unsure choose false.

        return new \PHPUnit_Extensions_Database_Operation_Composite(array(
            new TruncateOperation($cascadeTruncates),
            \PHPUnit_Extensions_Database_Operation_Factory::INSERT()
        ));
    }
}

所以我有效地禁用了外键检查并在它们被设置时将它们重新设置。显然,您应该创建一个具有此功能的基类并对其进行扩展,而不是 PHPUnit 的 TestCase。

【讨论】:

  • 你在哪里设置外键检查?
  • @Jeune 它在 TruncateOperation->execute 中被重置,第三行,它的位置是:“SET foreign_key_checks = 1”。在git上发现了这个问题,基本上是一样的,加了一些解释:DbUnit GIT
  • 不错的解决方案。我很想使用它,但作为一个控制狂,我宁愿确保正确输入数据而不是放松 FK 约束,所以我只是在setUp 方法中添加了一些自定义删除查询,然后我调用了parent::setUp,并且工作正常。
【解决方案2】:

或者,您可以通过删除所有记录然后重新设置自动增量计数器的组合来模拟截断。

首先,您必须创建新的数据库操作类来处理重置表的自动增量值。

/**
 * Resets all AUTO_INCREMENT counters on all tables in a dataset.
 * @see PHPUnit_Extensions_Database_Operation_IDatabaseOperation
 */
class ResetAutoincrementOperation implements PHPUnit_Extensions_Database_Operation_IDatabaseOperation
{

    /* 
     * @see PHPUnit_Extensions_Database_Operation_IDatabaseOperation::execute()
     */
    public function execute(PHPUnit_Extensions_Database_DB_IDatabaseConnection $connection, 
            PHPUnit_Extensions_Database_DataSet_IDataSet $dataSet)
    {
        foreach ($dataSet->getReverseIterator() as $table) {
            $query = "ALTER TABLE {$connection->quoteSchemaObject($table->getTableMetaData()->getTableName())}"
                . " AUTO_INCREMENT = 1
            ";

            try {
                $connection->getConnection()->query($query);
            } catch (PDOException $e) {
                throw new PHPUnit_Extensions_Database_Operation_Exception('RESET_AUTOINCREMENT', 
                        $query, array(), $table, $e->getMessage());
            }
        }
    }
}

现在如上所述覆盖getSetUpOperation()getTearDownOperation()方法。

class FooTest extends PHPUnit_Extensions_Database_TestCase
{
    /**
     * @see PHPUnit_Extensions_Database_TestCase::getTearDownOperation()
     */
    protected function getTearDownOperation ()
    {
        // Clean up after ourselves
        return new PHPUnit_Extensions_Database_Operation_Composite(array(
            PHPUnit_Extensions_Database_Operation_Factory::DELETE_ALL(), // 1. delete all records from table
            new ResetAutoincrementOperation() // 2. reset auto increment value
        ));
    }

    /**
     * @see PHPUnit_Extensions_Database_TestCase::getSetUpOperation ()
     */
    protected function getSetUpOperation ()
    {
        return new PHPUnit_Extensions_Database_Operation_Composite(array(
                PHPUnit_Extensions_Database_Operation_Factory::DELETE_ALL(), // 1. delete all records from table
                new ResetAutoincrementOperation(), // 2. reset auto increment value
                PHPUnit_Extensions_Database_Operation_Factory::INSERT() // 3. insert new records
        ));
    }
}

使用 MySQL 5.5.24 和 PHPUnit 3.6.10 为我工作

【讨论】:

    【解决方案3】:
    \DB::statement('SET FOREIGN_KEY_CHECKS=0;');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-29
      • 2010-11-03
      • 2011-09-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多