php 使用数据库进行 Phpunit 测试

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4585345/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 13:34:33  来源:igfitidea点击:

Phpunit testing with database

phpunit-testingzend-frameworkphpunit

提问by sanders

I am trying to focus a bit on unit testing using PHPunit.

我正在尝试将重点放在使用 PHPunit 的单元测试上。

I have found a very good tutorial over here http://blog.nickbelhomme.com/php/phpunit-training-course-for-free_282

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

But there is something I miss and don't yet understand how to do.

但是有些事情我很想念,还不知道该怎么做。

I have a user module wich maintains all information about users. And There is a function save which saves the user in the database. So I have a testFunction

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

public function testCanCreateUser()
{
    $userData = array(
        'userName'  =>  'User1',
        'firstName' =>  'Joey',
        'lastName'  =>  'Hendricks',
        'email'     =>  '[email protected]',
        'password'  =>  'f$tfe8F'

    ); 
    $user = new Model_User($userData);
    $user->save();

}

The first time when I will run my test this wil work. Since the database is empty. But When I run my tests for the second time it won't work since my system doesn't allow the same user twice in the db. So In order to do this I have to recreate my testdatabase every time before I run my tests. What is the best way to do this? Or is this problem to be solved on a different way?

当我第一次运行我的测试时,这将起作用。因为数据库是空的。但是当我第二次运行我的测试时它不会工作,因为我的系统不允许同一个用户在数据库中两次。所以为了做到这一点,我必须在每次运行测试之前重新创建我的测试数据库。做这个的最好方式是什么?或者这个问题要以不同的方式解决?

Tnx.

Tnx。

回答by edorian

If you want to test your business logic:Mock away the Database class and return fake data

如果你想测试你的业务逻辑:模拟数据库类并返回假数据

If you want to test the class that fires the SQL statements(and imho you could test that too since I kinda wanna know if my code works fine with a real db in the backend) it gets a little complicated but there are ways to do it:

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

  • Using setUp() and tearDown() to get a consistent state for your data before running your tests is (imho) a fine way to write db-driven unittests. It can get annoying to write lots of custom sql by hand though.

  • To make your life a little easier you can look into the DbUnit extensionand see if that works for your Application.

  • If you reallywant to dive into Unittesting database interactions the best read on the subject is (imho) the chapter on db-unittesting in Sebastian Bergmanns phpqa book.

  • Could your application allow for a custom database name and automated setup of all tables it may also be possible to set the db up once with a lot of testdata and use that data in all your tests. You could be carefull so though that one test doesn't rely on data written by another one.

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

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

  • 如果您真的想深入了解 Unittesting 数据库交互,那么关于该主题的最佳读物是(恕我直言)Sebastian Bergmanns phpqa book 中关于 db-unittesting 的章节。

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

回答by Kornel

Run tests with other copy of the database that is empty and/or cleared in setUp()or tearDown()methods, but be careful not to do what github did.

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

If you're using a good database (i.e. not MySQL with MyISAM tables) you can wrap test in a transaction and roll it back after the test:

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

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

The downside is that you can't test code that uses transactions (unless you abstract that and emulate with savepoints, but that's iffy).

缺点是您无法测试使用事务的代码(除非您对其进行抽象并使用保存点进行模拟,但这是不确定的)。

Ideally you should use dependency injection and run tests on fake database class:

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

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

回答by subosito

I think you can use tearDown()method to clean your saved data.

我认为您可以使用tearDown()方法来清理保存的数据。

protected $_user;

public function testCanCreateUser()
{
    ...

    $this->_user = new Model_User($userData);
    $this->_user->save();
}

public function tearDown()
{
    $this->_user->delete();
}