phpunit使用silex php测试映射器

phpunit使用silex php测试映射器,php,phpunit,silex,Php,Phpunit,Silex,我想测试我的class LocationMapper,其目标是进行CRUD操作: <?php class LocationMapper { /* * Database connection. */ var $db = NULL; /* * Constructor function. Loads model from database if the id is known. * * @param $db * Database connection */ function __cons

我想测试我的class LocationMapper,其目标是进行CRUD操作:

<?php
class LocationMapper {
/*
* Database connection.
*/
var $db = NULL;


/*
* Constructor function. Loads model from database if the id is known.
*
* @param $db
*   Database connection
*/
function __construct($app) {    
    $this->db = $app['db'];
}

    /**
    * Load data from the db for an existing user.
    */
    function read($app, $id) {
    $statement = $this->db->prepare('SELECT * FROM location WHERE id = :id');
    $statement->execute(array(':id' => $id));
    $data = $statement->fetch(PDO::FETCH_ASSOC);
    $comments = $app['CommentMapper']->loadAllByLocation($id);
    $location = new Location($data['latitude'], $data['longitude'],     $data['address'], $data['name'], $data['checked'], $comments);
    $location->set('id', $data['id']);
    return $location;
   }
    ...
}
如何使用真实数据库测试类LocationMapper? 我测试了这个:

class LocationMapperTest extends PHPUnit_Framework_TestCase
{
    protected $locationMapper;
    protected $app;

    public function setUp() {
        $app = new Silex\Application();       

        // Add the database connection as a shared service to the container.
        $db_string = 'mysql:host=' . $app['db.hostname'] .';dbname=' . $app['db.dbname'];
        $app['db'] = $app->share(function ($app) use ($db_string) {
        try {
           return new PDO($db_string, $app['db.username'], $app['db.password']);
        }
        catch (PDOException $e) {
           $app->abort(500, 'Unable to connect to database.  Check your configuration');
        }
        });
        $locationMapper = new LocationMapper();
   }

   public function createTest() {        
        $this->assertEquals(0, 0);
   }
}

但是我有一个错误
PHP致命错误:找不到类'Silex\Application'

我猜您已经使用Composer安装了Silex,因此您在应用程序的最开始(可能在config.PHP中)自动加载Composer,以自动包含所有需要的文件。 问题是PHPUnit没有使用您的配置文件,因此它没有自动加载类:PHPUnit不会使用自动加载文件,除非您告诉它这样做

要告诉PHPUnit加载自动加载文件,您有两个选项:

第一个是在命令行上执行测试时使用。这样,PHPUnit将在测试执行开始时包含引导文件。如果您将自动加载文件传递给它,它将自动加载您的类

第二个选项是使用,其中指定引导文件

除此之外,还有一些关于代码的观察。单元测试不应该使用真实的数据库进行测试。这样,您的测试将修改真实数据库,使测试不可恢复(例如,如果删除行,您将不得不用数据重新填充数据库),速度会变慢,而且更重要的是,您可能会影响真实数据


我建议您模拟您的数据库,或者至少将数据库用于测试目的。

不模拟的单元测试?你应该远离任何“坚持”。请记住,unitTests应该在一个可能没有DB实例/互联网连接/API连接/移动摄像机设备/声音设备/或其他所需持久性的测试环境中运行。考虑一下数据库不可“本地”访问的系统。测试时更改数据也可能“更改”测试结果。Nice单元测试还将尝试在数据库中创建“脏数据”,以检查应用程序是否能够处理阻塞的db-data。谢谢您的回答。如何在$app['db']中创建一个模拟数据库?您的映射程序不应该在构造函数中接收整个应用程序,而应该只接收正在使用的colaborators:CommentMapper和db。通过此更改,您可以传入任何您需要的内容,以测试LocationMapper的行为,如虚拟Db对象或CommentMapper的模拟。你可以在这里阅读更多关于双打的内容
class LocationMapperTest extends PHPUnit_Framework_TestCase
{
    protected $locationMapper;
    protected $app;

    public function setUp() {
        $app = new Silex\Application();       

        // Add the database connection as a shared service to the container.
        $db_string = 'mysql:host=' . $app['db.hostname'] .';dbname=' . $app['db.dbname'];
        $app['db'] = $app->share(function ($app) use ($db_string) {
        try {
           return new PDO($db_string, $app['db.username'], $app['db.password']);
        }
        catch (PDOException $e) {
           $app->abort(500, 'Unable to connect to database.  Check your configuration');
        }
        });
        $locationMapper = new LocationMapper();
   }

   public function createTest() {        
        $this->assertEquals(0, 0);
   }
}