JQuery Venetian Blinds Transition Effect
Visualising Website Performance with Flame Graphs
ENUMs, User Preferences, and the MySQL SET Datatype
Book Review: How to Implement Design Patterns in PHP
Installing Xdebug for use with Eclipse or Netbeans on Linux
Symfony 2 Crash Course

PHPUnit Tests when a Class uses Multiple Databases

Wednesday, 26 June 13, 3:37 pm
PHPUnit supplies the PHPUnit_Extensions_Database_TestCase class which can be extended by your tests when you want to run tests that check the state of a database after some or all tests. This is all well and good, but you will soon notice that its methods that you override in your test class to connect to and populate a database (getConnection(), getDataSet()) only support a single database.

If you want to test code that accesses multiple databases, you can either:
  1. continue to use PHPUnit_Extensions_Database_TestCase and add code to set up connections to other databases in the setup() method
  2. extend PHPUnit_Framework_TestCase and make it populate and test multiple databases
For the first approach, connect to one of your databases in the getConnection() and getDataSet() methods as normal. For the second database, we're going to create and maintain a PHPUnit_Extensions_Database_DefaultTester object as a protected member variable of our test class.
/** * Used to test operations affecting a second database * * @var PHPUnit_Extensions_Database_DefaultTester */ protected $_dummyDatabase;
We set it up in the test class's setup() method:
public function setup() { parent::setUp();   // Now set up the second database $this->_dummyDatabase = new PHPUnit_Extensions_Database_DefaultTester( $this->createDefaultDBConnection( new PDO('mysql:host=localhost', 'dbuser', 'dbpass'), 'databaseName'));   // Populate it $this->_dummyDatabase->setDataset($this->createXMLDataSet(dirname(__FILE__) . '/datasets/dummydata.xml')); $this->_dummyDatabase->setSetUpOperation($this->getSetUpOperation()); $this->_dummyDatabase->setTearDownOperation($this->getTearDownOperation()); $this->_dummyDatabase->onSetup();   // Now put all the other crap you want here as normal }
For the second approach, you'll need to add a private member variable for each database your code needs, and set each one up in the setupBeforeClass() method:
/** * Stores database tester object for first db. * * @var PHPUnit_Extensions_Database_DefaultTester */ static private $_myGoodDatabase;   /** * Stores database tester object for second db. * * @var PHPUnit_Extensions_Database_DefaultTester */ static private $_myBadDatabase;   /** * Before all tests, set up database connections and global variables. * * @return void */ static public function setupBeforeClass() { parent::setupBeforeClass();   // Set up database connection and tester stuff self::$_myGoodDatabase = new PHPUnit_Extensions_Database_DefaultTester( new PHPUnit_Extensions_Database_DB_DefaultDatabaseConnection( Dada_DbManager::newPDO('goodDatabase'), Dada_DbManager::mapDatabaseName('goodDatabase')));   // Configure the data source self::$_myGoodDatabase->setDataSet( new PHPUnit_Extensions_Database_DataSet_XmlDataSet( dirname(__FILE__) . '/datasets/goodDatabase.xml'));   // Set up the setup/teardown actions self::$_myGoodDatabase->setSetUpOperation(PHPUnit_Extensions_Database_Operation_Factory::CLEAN_INSERT()); self::$_myGoodDatabase->setTearDownOperation(PHPUnit_Extensions_Database_Operation_Factory::NONE());   // Set up database connection and tester stuff self::$_myBadDatabase = new PHPUnit_Extensions_Database_DefaultTester( new PHPUnit_Extensions_Database_DB_DefaultDatabaseConnection( Dada_DbManager::newPDO('badDatabase'), Dada_DbManager::mapDatabaseName('badDatabase')));   // Configure the data source self::$_myBadDatabase->setDataSet( new PHPUnit_Extensions_Database_DataSet_XmlDataSet(dirname(__FILE__) . '/datasets/badDatabase.xml'));   // Set up the setup/teardown actions self::$_myBadDatabase->setSetUpOperation( PHPUnit_Extensions_Database_Operation_Factory::CLEAN_INSERT()); self::$_myBadDatabase->setTearDownOperation( PHPUnit_Extensions_Database_Operation_Factory::NONE());   }
We also need some methods for cleanup and setup tasks:
/** * After all tests have finished, tear down connections and release objects. * * @return void */ static public function tearDownAfterClass() { self::$_myGoodDatabase = null; self::$_myBadDatabase = null; parent::tearDownAfterClass(); }   /** * Before each test run the DB setup to load test data. * * @return void */ public function setUp() { parent::setUp();   self::$_myGoodDatabase->onSetUp(); self::$_myBadDatabase->onSetUp(); }   /** * After each test run the DB cleanup. * * @return void */ public function tearDown() { self::$_myGoodDatabase->onTearDown(); self::$_myBadDatabase->onTearDown(); parent::tearDown(); }

Hike Molloway

10:52 am, Wednesday, 24 September 14

I feel lucky to have stumbled across such a gem in the rough of Internet wisdom.

O. Rößner

12:11 pm, Thursday, 6 August 15

Thank you, helped me alot!

Please enter your comment in the box below. Comments will be moderated before going live. Thanks for your feedback!

Cancel Post

/xkcd/ Exclusion Principle