Set foreign key constraints off in PHPUnit/DBUnit
Asked Answered
A

3

11

I am developing Unit tests for testing model functions.

I am using PHP PDO with DBUnit 1.1.2 and PHPUnit 3.6.10 and my dataset is a yml file.

I need to turn off foreign key checks while the fixtures are being loaded in the database. After that I need to turn it on again so that I can run my tests under those constraints.

Below is a snippet (not the entire class file) of code in my generalized Testcase file which I will include for any new test case I develop.

When I run a test case under these settings these settings i found that $pdo->exec() is not executing.

What is wrong with my approach? Is there a better alternative?

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();
}
Apotheosis answered 28/3, 2012 at 8:54 Comment(2)
i'd love a better solution too. but this should workProrogue
and the better solution is here: #10331945Prorogue
B
16

Change your function setUp like this

protected function setUp() {
   $conn=$this->getConnection();
   $conn->getConnection()->query("set foreign_key_checks=0");
   parent::setUp();
    $conn->getConnection()->query("set foreign_key_checks=1");
}
Baggott answered 10/6, 2013 at 22:13 Comment(2)
This may have worked previously, but not anymore. When DBUnit truncates a table, it will also disable checks, then re-enable it when done. So the checks are always re-enabled prior to any inserts.Chigger
I`ve found exact place, where this is done: Truncate.php. If you need to keep behavior from older versions of phpunit, you need to extend default truncate operation class, in a way similar to this: https://mcmap.net/q/799904/-phpunit-and-mysql-truncation-error, and do something opposite: do not touch foreign keys while truncating. This will give you the ability to disable foreign keys in your way and re-enable when you want.Redpencil
Z
4

Thanks to the comments from @user2045006 and @marcini, I've created the below solution for my project.

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");
    }
}
Zales answered 1/6, 2016 at 21:47 Comment(0)
R
1

Sometimes it can be a case of manually truncating the tables beforehand and ensuring the ordering of your dataset is correct i.e. parent table first and then the reliant child tables. You can then avoid setting foreign_key_checks every test

Rolfston answered 12/9, 2013 at 7:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.