【问题标题】:Set foreign key constraints off in PHPUnit/DBUnit在 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();
}

【问题讨论】:

标签: unit-testing pdo foreign-keys phpunit dbunit


【解决方案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 的行为,则需要扩展默认的截断操作类,类似于以下方式:stackoverflow.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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-24
      • 2023-03-03
      • 1970-01-01
      • 2012-05-20
      • 2014-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多