6

When using PHPUnit to test a class that relies on the database, the getDataSet() method provides data to serve as the test fixture for the entire suite of tests. That's great, but how does one provide data for a specific test? It's not unusual, especially when using minimized data sets, for each test to require different database data on top of the common data that all tests use. I know the PDO object is available, and in our case, the application's native DB object is also available (meaning, we can run raw queries or use other functionality in the app), but it would be nice to have a way to insert data that's driven off PHPUnit's DataSet containers so that all test data are handled in the same fashion for improved clarity and easier maintenance.

Is there some way to accomplish this?

2 Answers 2

8

You could follow such dirty trick:

protected function getDataSet()
{
    if (in_array($this->getName(), array('testA', 'testB', '...'))) {
        return $this->createXMLDataSet(__DIR__ . '/_fixtures/fistureA.xml');
    }

    return $this->createXMLDataSet(__DIR__ . '/_fixtures/fixtureB.xml');
}

Small note: $this->getName() returns the current test method name

An alternative approach is to re-run set up operations in the begin of the test:

public function testA()
{
    $this->getDatabaseTester()->setDataSet($this->createFlatXMLDataSet(__DIR__ . '/_fixtures/fixtureForTestA.xml'));
    $this->getDatabaseTester()->onSetUp();

    /* your test code */
}
Sign up to request clarification or add additional context in comments.

2 Comments

I think it was a lot simpler with earlier versions. Why did they make it complicated?
i shouldn't use dbunit at at all and write my own custom prepare datasets by the looks of it
5

It's a late answer but it could still be useful to some people I guess...

You can accomplish this by calling the execute method of a IDatabaseOperation which you can get from PHPUnit_Extensions_Database_Operation_Factory. You would basically use CLEAN_INSERT or INSERT.

As zerkms' second approach, you would call it at the beginning of each test that needs specific data. For instance:

public function testA() {
  PHPUnit_Extensions_Database_Operation_Factory::INSERT()
    ->execute($this->getConnection(), $this->createXMLDataSet(__DIR__.'/fixtureA.xml'));

  // Test code
}

However, the advantage of this solution is that the dataset of the whole test case remains unchanged, so:

  • Test methods remain independent from each other (whereas in zerkms' approach, if you don't / forget to specify a dataset in another test method, it would reuse the dataset from the previous (random?) method that changed the dataset, which is quite ugly and very error-prone IMHO). Here, any other test without such call at its beginning would just use the test case dataset as usual.
  • You can build your test dataset on top of the common (test case) dataset. If you use the INSERT operation (not CLEAN_INSERT), it will insert rows specific to the test after all rows from the common dataset. You could also use the DELETE operation to remove some unwanted rows from that common dataset.
  • BTW, not calling onSetUp() makes this work even if the set up operation of the test case has been changed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.