How to do unit test in PHP if using an ORM layer?

I have a class saying "Man." The ORM level generated corresponding objects based on the sql structure. The class person has a method: Get ($ id). The Get method calls the Person object and retrieves the field from the table.

Basically I want to do the following unit test: create a new person and check if the Get method returns the correct information.

How is the device tested in this state? Do I need to create a separate database (only structure) and create / select from this database? If the boostrap file loads the same configuration as the infrastructure I use, but changes the configuration file to work with a fake database? Do I have to clean a new database each after each test?

I also wandered when I saw your answers, if imitating an ORM response without actually creating a new database - is that not the way to go?

+7
source share
3 answers

How is the device tested in this state?

As a rule, you should divide your smarties mentally in two parts:

  • one part of your code is tested without a database, so you can drown out or make fun of the methods that provide access to the database.
  • Another part of your tests should work with the database, as it checks the correct use of ORM.

Do I need to create a separate database

It depends on your needs. Rails applications typically have testing / development / production environments β€” databases, configurations, storage directories. Testing is designed to run unit tests, dev for development and production to run the server in real time. During development, you work against the dev configuration and therefore your development database. For unit tests, the test env is used, which has the advantage that users in the database are not deleted or broken.

I like this concept; in my phpunit tests I often have a switch in bootstrap that changes which configuration file is loaded. Just remember that your development database often contains more data than one unit test need, and you probably manually processed that data and didn't want to lose. In addition, another database is not worth the money.

Do I have to clean a new database each after each test?

I basically clear only those tables that will be used in the test. Cleaning your database ensures that you don’t get any side effects from previous tests.

+8
source

Check out the Phactory . I prefer it over the database extensions included in PHPUnit, and it makes it very easy to insert records into your test db.

require_once 'Phactory/lib/Phactory.php'; Phactory::setConnection(new PDO('sqlite:test.db')); Phactory::define('user', array('name' => 'Test User', 'email' => ' user@example.com ')); $user = Phactory::create('user'); // creates a row in the 'users' table print("Hello, {$user->name}!"); // prints "Hello, Test User!" 

Your System Test (SUT) should connect to your test database. The idea is that you only fill out the entries you need for the method you are testing. The orm level should not matter if the test db has all the same tables and fields as your production database.

+4
source

PHPUnit also gives some help on this, see Database Testing .

Essentially, you can write test classes to extend PHPUnit_Extensions_Database_TestCase , and then use the getConnection() and getDataSet() functions to load data for the test.

 require_once 'PHPUnit/Extensions/Database/TestCase.php'; class PersonTest extends PHPUnit_Extensions_Database_TestCase { protected function getConnection() { $pdo = new PDO('mysql:host=localhost;dbname=application_test', 'root', ''); return $this->createDefaultDBConnection($pdo, 'application_test'); } protected function getDataSet() { return $this->createMySQLXMLDataSet('person.xml'); } 

Then you can pinpoint what you want to test in the database in XML.

You can also claim that the resulting DataSet from your tests is equal to what you expect:

 public function testCreate() { // Execute some code with your ORM to create a person. $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet($this->getConnection()); $actual->addTable('person'); $expected = $this->createMySQLXMLDataSet('person_create_expected.xml'); $this->assertDataSetsEqual($expected, $actual); } 

In this example, we only compare the resulting person table ... Thus, person_create_expected.xml should contain only the person table.

To create XML, you can use mysqldump .

 mysqldump --xml -t -u root -p application_test > person.xml 
+3
source

All Articles