2012-04-26 16 views
14

ja dostaję bólu głowy z zachowaniem phpunit dnia zawsze działa TRUNCATE przed włożeniem lamp bez pierwsze ustawienie klucza obcego kontrole OFF:PHPUnit i MySQL obcięcie błędu

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

Zasadniczo PHPUnit próbuje obciąć tabela przed wstawianiem urządzeń. Jak mogę to powiedzieć do SET FOREIGN_KEY_CHECKS=0;?

+0

Dzieje się tak nawet wtedy, gdy tabela przedstawieniu tabeli jesteś obcinania jest pusty. Na pewno jest to błąd MySQL, niezależnie od komentarzy: http://bugs.mysql.com/bug.php?id=54678 @Tower Solution to niestety jedyna opcja. – jmc

Odpowiedz

27

Znalazłem odpowiedź wydaje się. Zakończyłem niektóre metody przez rozszerzenie klasy.

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

Następnie Przykład użycia:

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

Więc ja skutecznie wyłączyć klucz obcy kontrole i ustawiając je z powrotem, jeśli zostały one kiedykolwiek ustawiony. Oczywiście powinieneś stworzyć klasę bazową, która ma tę funkcjonalność i rozszerzysz ją, zamiast PHPControl.

+0

Gdzie ustawiasz kontrole klucza zagranicznego? – Jeune

+0

@Jeune jest resetowany w TruncateOperation-> execute, trzeci wiersz, gdzie przechodzi: "SET foreign_key_checks = 1". Znalazłem ten problem na git, który w zasadzie robi to samo, z dodatkowym wyjaśnieniem: [DbUnit GIT] (https://gist.github.com/1319731) – qrazi

+0

Fajne rozwiązanie. Kusiło mnie, aby go użyć, ale jako maniak kontroli raczej wolałbym, aby dane były wprowadzane poprawnie w porównaniu z relaksującymi ograniczeniami FK, dlatego właśnie dodałem pewne niestandardowe zapytania usuwania w metodzie 'setUp', zanim nazwałem' parent :: setUp' i działał dobrze. –

3

Można również symulować obcięcie za pomocą kombinacji usuwania wszystkich rekordów, a następnie ponownie ustawić licznik automatycznych inkrementów.

Najpierw należy utworzyć nową klasę operacji bazy danych, która będzie obsługiwać resetowanie wartości auto-inkrementacji tabeli.

/** 
* 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()); 
      } 
     } 
    } 
} 

teraz zastąpić metody getSetUpOperation() i getTearDownOperation() jak opisano powyżej.

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

pracował dla mnie z MySQL 5.5.24 i 3.6.10 PHPUnit