dbunit in phpunit is not truncating the tables
Asked Answered
O

4

16

I am currently using PHPUnit and DBUnit for my project. I have a problem in DBUnit because DBUnit PHPUnit_Extensions_Database_TestCase­Src class does not seem to be truncating the existing data on the test db. So this makes my insertion tests fail after only working for one time.

I am using mysql and here is my code :

abstract class Generic_Tests_DatabaseTestCase extends PHPUnit_Extensions_Database_TestCase
{
    // only instantiate pdo once for test clean-up/fixture load
    static private $pdo = null;

    // only instantiate PHPUnit_Extensions_Database_DB_IDatabaseConnection once per test
    private $conn = null;

    final public function getConnection()
    {
        if ($this->conn === null) {
            if (self::$pdo == null) {
                self::$pdo = new PDO( "mysql:dbname=db;host=localhost", "root", "pass" );
            }
            $this->conn = $this->createDefaultDBConnection(self::$pdo, "db");
        }

        return $this->conn;
    }
}

class DbopTest extends Generic_Tests_DatabaseTestCase
{       
    private $db;

    protected function setup(){
        $this->db = null;
    }

    public function getDataSet(){
        return $this->createMySQLXMLDataSet(dirname(__FILE__) . '/../rows.xml');
    }       
    ...
}

So how can I fix this problem? What is it that I do wrong here?

Obit answered 28/2, 2012 at 21:58 Comment(5)
Where does the wished truncation take's place? Which version of PHPUnit and which version of DBUnit are you using?Flop
thats the problem, i think in my getDataSet method, truncation operates automatically. But I cant see that happen. I am using PHP Unit 3.6.10.Obit
It's just a guess, but you're overwriting the setUp() method. Please check if getDataSet() is still being called.Flop
yeah, when i call the parent::setup the problem is fixed, good guess ; )Obit
+1 Useful question because of the use of getDataSet and use of Generic DataTest class!Cholula
F
37

If you override the setUp method, PHPUnit won't automatically call your getDataSet method. You need to take care that you call the parent::setUp method as well, otherwise PHPUnit does not know what to do ;).

Flop answered 29/2, 2012 at 22:53 Comment(1)
I am not overriding the setUp method in my tests, but it's still not truncating the table. At what point does DBUnit actually truncate the database?Shame
T
5

I came across this issue myself and this is how I resolved it after a bit of digging into the PHPUnit sourcecode. It looks like the default behavior for the PHPUnit_Extensions_Database_TestCase class is to return PHPUnit_Extensions_Database_Operation_Factory::NONE(). For what you need, and how the PHPUnit document seems to imply how it's supposed to work, you'll want to override the method to return PHPUnit_Extensions_Database_Operation_Factory::TRUNCATE().

Luckily, this is fairly straight-forward. You just need to add the following to your TestCase class.

protected function getTearDownOperation()
{
    return \PHPUnit_Extensions_Database_Operation_Factory::TRUNCATE();
}

Before this I was manually truncating tables in my Teardown() method, but I think you'll agree that this solution is much better.

Tychonn answered 11/2, 2014 at 23:13 Comment(1)
This method definitely works but in "phpunit/phpunit": "^7.0.0" and "phpunit/dbunit": "^4.0" you need to use return \PHPUnit\DbUnit\Operation\Factory::TRUNCATE();Geller
C
1

Not expecting many too kudos for this answer, but I have spent several hours trying to figure out why one of my test database tables was not getting truncated, causing the same duplicate entry error described above. My getDataSet() looked like

function getDataSet() {

    $files = array('languages','interpreters','interp_languages',
        'interp_events','deft_events',
           //etc
    );

    $dataSets = array();
    foreach ($files as $file) {
        $dataSets[] = new PHPUnit_Extensions_Database_DataSet_MysqlXmlDataSet(
         $this->files_dir."/$file.xml");
    }

    return new PHPUnit_Extensions_Database_DataSet_CompositeDataSet($dataSets);
}

and the technique was working fine on other test classes. It happens that I inadvertentely left out one of my xml data file names from $files, therefore DbUnit was not loading that data file, ergo not truncating the table. But because there were plenty of rows left over in the table from other tests that were using that same data file, it was not obvious (to me) what was happening.

Hope it saves someone else from tearing her/his eyeballs out some day.

Cluck answered 17/4, 2014 at 18:24 Comment(0)
C
0

You need to have a getDataSet() method otherwise PHPUnit assumes you have no data to fixturize.

http://www.phpunit.de/manual/3.6/en/database.html

The getDataSet() method defines how the initial state of the database should look before each test is executed. The state of a database is abstracted through the concepts DataSet and DataTable both being represented by the interfaces PHPUnit_Extensions_Database_DataSet_IDataSet and PHPUnit_Extensions_Database_DataSet_IDataTable. The next section will describe in detail how these concepts work and what the benefits are for using them in database testing.

For the implementation we only need to know that the getDataSet() method is called once during setUp() to retrieve the fixture data-set and insert it into the database. In the example we are using a factory method createFlatXMLDataSet($filename) that represents a data-set through an XML representation.

Coronograph answered 28/2, 2012 at 22:24 Comment(1)
you can see that my DbopTest method has a getDataSet method, and it creates dataset from a mysqldump file.Obit

© 2022 - 2024 — McMap. All rights reserved.