使用数据库进行 Phpunit 测试

2022-08-30 20:34:33

我试图把重点放在使用PHPunit进行单元测试上。

我在这里找到了一个非常好的教程 http://blog.nickbelhomme.com/php/phpunit-training-course-for-free_282

但是我错过了一些东西,还不明白该怎么做。

我有一个用户模块,它维护有关用户的所有信息。并且有一个函数保存,它将用户保存在数据库中。所以我有一个测试函数

public function testCanCreateUser()
{
    $userData = array(
        'userName'  =>  'User1',
        'firstName' =>  'Joey',
        'lastName'  =>  'Hendricks',
        'email'     =>  'Joey@hendricks.com',
        'password'  =>  'f$tfe8F'
    
    ); 
    $user = new Model_User($userData);
    $user->save();
     
}

当我第一次运行测试时,这将起作用。由于数据库为空。但是当我第二次运行测试时,它将不起作用,因为我的系统不允许同一用户在数据库中两次。因此,为了做到这一点,我必须在每次运行测试之前重新创建我的testdatabase。最好的方法是什么?

还是这个问题要以不同的方式解决?


答案 1

如果要测试业务逻辑:模拟数据库类并返回虚假数据

如果你想测试触发SQL语句的类(恕我直言,你也可以测试它,因为我有点想知道我的代码是否与后端的真实数据库一起工作良好),它会变得有点复杂,但有办法做到这一点:

  • 在运行测试之前,使用 setUp() 和 tearDown() 为数据获取一致的状态是(恕我直言)编写数据库驱动的单元测试的好方法。但是,手动编写大量自定义sql可能会很烦人。

  • 为了让您的生活更轻松一些,您可以查看DbUnit扩展,看看它是否适用于您的应用程序。

  • 如果你真的想深入研究单元测试数据库交互,那么关于这个主题的最佳阅读是(恕我直言)Sebastian Bergmanns phpqa书中关于db-unittesting的章节。

  • 您的应用程序是否允许自定义数据库名称并自动设置所有表,也可以使用大量测试数据设置数据库一次,并在所有测试中使用该数据。你可以小心,这样一个测试就不会依赖于另一个测试写入的数据。


答案 2

使用空的和/或清除的数据库的其他副本运行测试 or 方法,但要注意不要执行 github 所做的操作setUp()tearDown()

如果您使用的是一个好的数据库(即不是MySQL和MyISAM表),则可以将测试包装在事务中并在测试后回滚:

 function setUp() { $this->db->exec("BEGIN"); }
 function tearDown() { $this->db->exec("ROLLBACK"); }

缺点是你不能测试使用事务的代码(除非你抽象出来并使用保存点进行模拟,但这很糟糕)。

理想情况下,您应该使用依赖注入并对假数据库类运行测试:

$fakedb = new DatabaseThatDoesntReallySaveThings();
$user = new Model_User($fakedb, $userData);
$user->save();
$this->assertTrue($fakedb->wasAskedToSaveUser());

推荐