2012-04-26 8 views
14

मैं हमेशा बिना TRUNCATE चल डालने जुड़नार करने से पहले पहले विदेशी कुंजी चेकों दूर सेटिंग की PHPUnit के व्यवहार के साथ सिर में दर्द हो रही है:PHPUnit और MySQL काट-छांट त्रुटि

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

असल में, PHPUnit एक काट-छांट करने की कोशिश करता फिक्स्चर डालने से पहले टेबल। मैं इसे SET FOREIGN_KEY_CHECKS=0; पर कैसे कहूं?

+0

साथ मेरे लिए काम किया यह तब होता है, जब भी तालिका तालिका आप को छोटा कर रहे हैं को संदर्भित खाली है। बहुत यकीन है कि यह एक MySQL बग है, यहां पर टिप्पणियों के बावजूद: http://bugs.mysql.com/bug.php?id=54678 @ टावर समाधान दुखद रूप से एकमात्र विकल्प है। – jmc

उत्तर

27

मुझे ऐसा लगता है कि ऐसा लगता है। मैंने कक्षा को विस्तारित करके कुछ तरीकों को ओवरराइड कर दिया।

<?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 के टेस्टकेस के बजाय बढ़ाएं।

+0

आप विदेशी कुंजी चेक कहां सेट कर रहे हैं? – Jeune

+0

@Jeune इसे TruncateOperation-> निष्पादित, तीसरी पंक्ति में रीसेट किया गया है, जहां यह जाता है: "SET foreign_key_checks = 1"। इस मुद्दे को गिट पर मिला, जो मूल रूप से वही करता है, कुछ अतिरिक्त स्पष्टीकरण के साथ: [डीबीयूनीट जीआईटी] (https://gist.github.com/1319731) – qrazi

+0

अच्छा समाधान। मैं इसका उपयोग करने के लिए लुभाना चाहता था, लेकिन एक नियंत्रण सनकी के रूप में, मैं यह सुनिश्चित करना चाहता हूं कि एफके बाधाओं को आराम से बनाकर डेटा सही ढंग से दर्ज किया गया है, इसलिए मैंने 'सेटअप' विधि में कुछ कस्टम डिलीट क्वेरीज जोड़े हैं, इससे पहले कि मैंने 'पैरेंट :: सेटअप ', और ठीक काम किया। –

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() और 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