14

最初に外部キーチェックをオフに設定せずTRUNCATEに、フィクスチャを挿入する前に常に実行するというPHPUnitの動作に頭痛の種があります。

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

基本的に、PHPUnitは、フィクスチャを挿入する前にテーブルを切り捨てようとします。どうすればわかりますSET FOREIGN_KEY_CHECKS=0;か?

4

3 に答える 3

28

私はそれが思われる答えを見つけました。クラスを拡張することで、いくつかのメソッドをオーバーライドすることになりました。

<?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 ではなくそれを拡張する必要があります。

于 2012-04-26T10:48:02.877 に答える
3

または、すべてのレコードを削除してから自動インクリメント カウンターを再設定することを組み合わせて、切り捨てをシミュレートすることもできます。

まず、テーブルの自動インクリメント値のリセットを処理する新しいデータベース操作クラスを作成する必要があります。

/**
 * 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()andメソッドを上書きします。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 で動作しました

于 2012-06-20T23:12:32.247 に答える
0
\DB::statement('SET FOREIGN_KEY_CHECKS=0;');
于 2019-06-24T05:57:39.957 に答える