在 PHPUnit/DBUnit 中设置外键约束

Posted

技术标签:

【中文标题】在 PHPUnit/DBUnit 中设置外键约束【英文标题】:Set foreign key constraints off in PHPUnit/DBUnit 【发布时间】:2012-04-11 20:17:30 【问题描述】:

我正在开发用于测试模型功能的单元测试。

我正在使用带有 DBUnit 1.1.2 和 phpUnit 3.6.10 的 PHP PDO,我的数据集是一个 yml 文件。

在将灯具加载到数据库中时,我需要关闭外键检查。之后我需要再次打开它,以便我可以在这些限制下运行我的测试。

下面是我的通用测试用例文件中的一个 sn-p(不是整个类文件)代码,我将包含在我开发的任何新测试用例中。

当我在这些设置下运行测试用例时,我发现 $pdo->exec() 没有执行。

我的方法有什么问题?有更好的选择吗?

class MyTestCase extends PHPUnit_Extensions_Database_TestCase 

public function getConnection() 
  $this->pdo = $this->getPDO();

  echo "BEFORE FOREIGN KEY QUERY\n";
  $conn =  $this->createDefaultDBConnection($this->pdo, 'my-schema');
  $this->pdo->exec("set foreign_key_checks=0");

  return $conn;


private function getPDO() 
  include BASEPATH . '/application/config/database.php';
  $dbt = $db['testing'];
  $conn_string = sprintf("%s:host=%s;dbname=%s", $dbt['dbdriver'], $dbt['hostname'],     $dbt['database']);
  $pdo = new PDO($conn_string, $dbt['username'], $dbt['password']);
  return $pdo;


public function getDataSet() 
  echo "BEFORE FOREIGN KEY QUERY in getDataSet\n";
  $this->pdo->exec("set foreign_key_checks=1");
  return new PHPUnit_Extensions_Database_DataSet_YamlDataSet(ROOTPATH."/application/tests/data/my-dataset.yml");


public function setUp() 
   parent::setUp();

【问题讨论】:

我也想要一个更好的解决方案。但这应该工作 更好的解决方案在这里:***.com/questions/10331445/… 【参考方案1】:

像这样改变你的函数设置

protected function setUp() 
   $conn=$this->getConnection();
   $conn->getConnection()->query("set foreign_key_checks=0");
   parent::setUp();
    $conn->getConnection()->query("set foreign_key_checks=1");

【讨论】:

这可能以前有效,但不再有效。当 DBUnit 截断一个表时,它也会禁用检查,然后在完成时重新启用它。所以检查总是在任何插入之前重新启用。 我找到了完成此操作的确切位置:Truncate.php。如果您需要保留旧版本 phpunit 的行为,则需要扩展默认的截断操作类,类似于以下方式:***.com/a/10331869/1844362,并做相反的事情:截断时不要触摸外键。这将使您能够以自己的方式禁用外键并在需要时重新启用。【参考方案2】:

感谢@user2045006 和@marcini 的cmets,我为我的项目创建了以下解决方案。

class MyDbTestCase extends PHPUnit_Extensions_Database_TestCase

    protected function getConnection()
    
        // ... as normal ...
    

    protected function getSetUpOperation()
    
        // Override
        return new PHPUnit_Extensions_Database_Operation_Composite([
            PHPUnit_Extensions_Database_Operation_Factory::TRUNCATE(),
            new InsertOperationWithoutFkChecks(),
        ]);
    



// Custom subclass
class InsertOperationWithoutFkChecks extends PHPUnit_Extensions_Database_Operation_Insert

    public function execute(
        PHPUnit_Extensions_Database_DB_IDatabaseConnection $connection,
        PHPUnit_Extensions_Database_DataSet_IDataSet $dataSet
    ) 
        $connection->getConnection()->exec("SET foreign_key_checks = 0");
        parent::execute($connection, $dataSet);
        $connection->getConnection()->exec("SET foreign_key_checks = 1");
    

【讨论】:

【参考方案3】:

有时可能需要事先手动截断表并确保数据集的顺序正确,即首先是父表,然后是依赖子表。然后,您可以避免在每个测试中设置 foreign_key_checks

【讨论】:

以上是关于在 PHPUnit/DBUnit 中设置外键约束的主要内容,如果未能解决你的问题,请参考以下文章

怎么在SQL中设置外键

在 phpMyAdmin 中设置外键

在 phpMyAdmin 中设置外键?

在 phpMyAdmin 中设置外键?

PD中设置外键约束名称生成规则

SQL中如何为表添加外键约束