phpunit 中的 dbunit 不会截断表
Posted
技术标签:
【中文标题】phpunit 中的 dbunit 不会截断表【英文标题】:dbunit in phpunit is not truncating the tables 【发布时间】:2012-03-18 10:10:33 【问题描述】:我目前正在为我的项目使用 phpUnit 和 DBUnit。我在 DBUnit 中有一个问题,因为 DBUnit PHPUnit_Extensions_Database_TestCase
Src 类似乎没有截断测试数据库上的现有数据。所以这使得我的插入测试只工作了一次就失败了。
我正在使用 mysql,这是我的代码:
abstract class Generic_Tests_DatabaseTestCase extends PHPUnit_Extensions_Database_TestCase
// only instantiate pdo once for test clean-up/fixture load
static private $pdo = null;
// only instantiate PHPUnit_Extensions_Database_DB_IDatabaseConnection once per test
private $conn = null;
final public function getConnection()
if ($this->conn === null)
if (self::$pdo == null)
self::$pdo = new PDO( "mysql:dbname=db;host=localhost", "root", "pass" );
$this->conn = $this->createDefaultDBConnection(self::$pdo, "db");
return $this->conn;
class DbopTest extends Generic_Tests_DatabaseTestCase
private $db;
protected function setup()
$this->db = null;
public function getDataSet()
return $this->createMySQLXMLDataSet(dirname(__FILE__) . '/../rows.xml');
...
那么我该如何解决这个问题呢?我在这里做错了什么?
【问题讨论】:
希望的截断发生在哪里?您使用的是哪个版本的 PHPUnit 和哪个版本的 DBUnit? 这就是问题所在,我认为在我的 getDataSet 方法中,截断会自动运行。但我看不到这种情况发生。我正在使用 PHP 单元 3.6.10。 这只是一个猜测,但您正在覆盖setUp()
方法。请检查getDataSet()
是否仍在被调用。
是的,当我调用 parent::setup 时,问题已解决,猜得好; )
+1 有用的问题,因为使用 getDataSet 和使用 Generic DataTest 类!
【参考方案1】:
如果你覆盖setUp
方法,PHPUnit 不会自动调用你的getDataSet
方法。您还需要注意调用parent::setUp
方法,否则PHPUnit 不知道该怎么做;)。
【讨论】:
我没有在我的测试中重写 setUp 方法,但它仍然没有截断表格。 DBUnit 在什么时候实际截断数据库?【参考方案2】:我自己也遇到了这个问题,这就是我在深入研究 PHPUnit 源代码后解决它的方法。看起来 PHPUnit_Extensions_Database_TestCase 类的默认行为是返回 PHPUnit_Extensions_Database_Operation_Factory::NONE()。对于您需要什么,以及 PHPUnit 文档似乎暗示它应该如何工作,您需要重写返回 PHPUnit_Extensions_Database_Operation_Factory::TRUNCATE() 的方法。
幸运的是,这是相当直截了当的。您只需将以下内容添加到您的 TestCase 类中。
protected function getTearDownOperation()
return \PHPUnit_Extensions_Database_Operation_Factory::TRUNCATE();
在此之前,我在 Teardown() 方法中手动截断表,但我想你会同意这个解决方案要好得多。
【讨论】:
这个方法确实有效,但是在"phpunit/phpunit": "^7.0.0"
和"phpunit/dbunit": "^4.0"
你需要使用return \PHPUnit\DbUnit\Operation\Factory::TRUNCATE();
【参考方案3】:
没想到这个答案会有太多的荣誉,但我花了几个小时试图弄清楚为什么我的一个测试数据库表没有被截断,导致上述相同的重复输入错误。我的 getDataSet() 看起来像
function getDataSet()
$files = array('languages','interpreters','interp_languages',
'interp_events','deft_events',
//etc
);
$dataSets = array();
foreach ($files as $file)
$dataSets[] = new PHPUnit_Extensions_Database_DataSet_MysqlXmlDataSet(
$this->files_dir."/$file.xml");
return new PHPUnit_Extensions_Database_DataSet_CompositeDataSet($dataSets);
并且该技术在其他测试类上运行良好。碰巧我无意中从 $files 中遗漏了我的 xml 数据文件名之一,因此 DbUnit 没有加载该数据文件,因此没有截断表格。但是由于使用相同数据文件的其他测试在表中留下了很多行,所以(对我来说)发生了什么并不明显。
希望有一天它可以避免其他人将她/他的眼球撕裂。
【讨论】:
【参考方案4】:您需要有一个 getDataSet()
方法,否则 PHPUnit 会假定您没有要修复的数据。
http://www.phpunit.de/manual/3.6/en/database.html
getDataSet() 方法定义了在执行每个测试之前数据库的初始状态应该如何显示。数据库的状态是通过概念 DataSet 和 DataTable 抽象出来的,这两个概念都由接口 PHPUnit_Extensions_Database_DataSet_IDataSet 和 PHPUnit_Extensions_Database_DataSet_IDataTable 表示。下一节将详细描述这些概念的工作原理以及在数据库测试中使用它们的好处。
对于实现,我们只需要知道在 setUp() 期间调用一次 getDataSet() 方法即可检索夹具数据集并将其插入数据库。在示例中,我们使用了工厂方法 createFlatXMLDataSet($filename),它通过 XML 表示来表示数据集。
【讨论】:
你可以看到我的 DbopTest 方法有一个 getDataSet 方法,它从 mysqldump 文件创建数据集。以上是关于phpunit 中的 dbunit 不会截断表的主要内容,如果未能解决你的问题,请参考以下文章
如何加快 PHPUnit + DBUnit 测试套件的执行速度?