Mocking PDO with phpunit

笑着哭i 提交于 2021-02-06 09:58:23

问题


I am trying to mock PDO object to use when writing some tests with phpunit, but I find it pretty complicated and can't find too much documentation about it. I created this xml structure:

<dataset>
    <table name="providers">
            <column>id</column>
            <column>name</column>
            <column>description</column>
            <row>
                    <value>1</value>
                    <value>provdier_1</value>
                    <value>phpunit first provider</value>
            </row>
    </table>
</dataset>

and now I want to query providers table and get the data back but I just cant figure out how to do that.

I started with mocking the PDO object but I don't understand how should I work with it and how to use it inside the getConnection() method. my first attempt, which I'm guessing its quite far from the correct way because I am very lost here, looks something like this:

class AdProvidersTest extends PHPUnit_Extensions_Database_TestCase
{
    public function getConnection()
    {
      $dsn = 'mydb';
      $user = '';
      $password = '';

      $pdo = $this->getMockBuilder('PDOMock')
        ->getMock();

        return $this->createDefaultDBConnection($pdo, 'adserverTesting');
    }

    public function getDataSet()
    {
        return $this->createXMLDataSet('adserverTesting.xml');
    }

}

how can I make the connection interact with the 'adserverTesting.xml' file and how can I query it using this lines:

$ds = new PHPUnit_Extensions_Database_DataSet_QueryDataSet($this->getConnection());
$ds->addTable('adserverTesting', 'SELECT * FROM providers');

回答1:


You don't have to mock PDO. Here example how it works:

ConnectionTest.php:

<?php

class ConnectionTest extends PHPUnit_Extensions_Database_TestCase
{
    public function getConnection()
    {
        $database = 'myguestbook';
        $user = 'root';
        $password = '';
        $pdo = new PDO('mysql:host=localhost;dbname=myguestbook', $user, $password);
        $pdo->exec('CREATE TABLE IF NOT EXISTS guestbook (id int, content text, user text, created text)');
        return $this->createDefaultDBConnection($pdo, $database);
    }

    public function getDataSet()
    {
        return $this->createFlatXMLDataSet(__DIR__.'/dataSets/myFlatXmlFixture.xml');
    }

    public function testGetRowCount()
    {
        $this->assertEquals(2, $this->getConnection()->getRowCount('guestbook'));
    }
}

myFlatXmlFixture.xml

<?xml version="1.0" ?>
<dataset>
    <guestbook id="1" content="Hello buddy!" user="joe" created="2010-04-24 17:15:23" />
    <guestbook id="2" content="I like it!" user="nancy" created="2010-04-26 12:14:20" />
</dataset>

Result:

PHPUnit 4.7.6 by Sebastian Bergmann and contributors.

.

Time: 215 ms, Memory: 5.25Mb

OK (1 test, 1 assertion)

Main point in tests against db is don't mock db but also create absolutely same PDO connection not to production db but to db for test, it can be mysql, sqlite etc...




回答2:


Have you tried viewing the documentation? They seem to be using a traditional PDO object using an in-memory sqlite connection by loading it with xml data like you are trying to do

<?php

class AdProvidersTest extends PHPUnit_Extensions_Database_TestCase
{
    /**
     * @return PHPUnit_Extensions_Database_DB_IDatabaseConnection
     */
    public function getConnection()
    {
        $pdo = new PDO('sqlite::memory:');
        return $this->createDefaultDBConnection($pdo, ':memory:');
    }
}

Edit: May 2020 - Unit tests are to test units of code, not to test your data sets. It is best practice to Mock your dependencies to return known data sets, not to query in-memory databases. Querying data is best suited for integration tests, which are an entirely different set of tests. See https://phpunit.readthedocs.io/en/9.1/test-doubles.html?highlight=database#stubs




回答3:


According to documentation createXMLDataSet xml file format is

 It is a very simple xml format where a tag inside the root node <dataset> represents exactly one row in the database. The tags name equals the table to insert the row into and an attribute represents the column.

And this xml file represents data(not schema).

I believe you want test your queries and results. So IMHO it will be better to use test DB and real connection. Migration tools like http://www.liquibase.org/ can be very helpful to prepare DB and than rollback it. Also you can use some fakers for you requests/data generation like https://packagist.org/packages/fzaninotto/faker



来源:https://stackoverflow.com/questions/31903097/mocking-pdo-with-phpunit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!