如何使用PHPUnit插入测试用例特定的数据库行


How to insert test case-specific database rows with PHPUnit

当使用PHPUnit测试依赖于数据库的类时,getDataSet()方法提供数据作为整个测试套件的测试夹具。这很好,但是如何为特定的测试提供数据呢?对于每个测试来说,在所有测试使用的公共数据之上都需要不同的数据库数据,这并不罕见,尤其是在使用最小化数据集的情况下。我知道PDO对象是可用的,在我们的情况下,应用程序的本地DB对象也是可用的(这意味着,我们可以运行原始查询或在应用程序中使用其他功能),但最好有一种方法来插入由PHPUnit的DataSet容器驱动的数据,以便以相同的方式处理所有测试数据,以提高清晰度并更容易维护。

有什么办法可以做到这一点吗?

你可以遵循这样的肮脏伎俩:

protected function getDataSet()
{
    if (in_array($this->getName(), array('testA', 'testB', '...'))) {
        return $this->createXMLDataSet(__DIR__ . '/_fixtures/fistureA.xml');
    }
    return $this->createXMLDataSet(__DIR__ . '/_fixtures/fixtureB.xml');
}

小提示:$this->getName()返回当前测试方法名称

另一种方法是在测试开始时重新运行设置操作:

public function testA()
{
    $this->getDatabaseTester()->setDataSet($this->createFlatXMLDataSet(__DIR__ . '/_fixtures/fixtureForTestA.xml'));
    $this->getDatabaseTester()->onSetUp();
    /* your test code */
}

这是一个迟来的答案,但我想它对一些人仍然有用。。。

您可以通过调用IDatabaseOperationexecute方法来实现这一点,该方法可以从PHPUnit_Extensions_Database_Operation_Factory中获得。您基本上会使用CLEAN_INSERTINSERT

作为zerkms的第二种方法,您可以在每次需要特定数据的测试开始时调用它。例如:

public function testA() {
  PHPUnit_Extensions_Database_Operation_Factory::INSERT()
    ->execute($this->getConnection(), $this->createXMLDataSet(__DIR__.'/fixtureA.xml'));
  // Test code
}

然而,这种解决方案的优点是整个测试用例的数据集保持不变,因此:

  • 测试方法彼此保持独立(而在zerkms的方法中,如果您不/忘记在另一个测试方法中指定数据集,它会重用更改数据集的前一个(随机?)方法中的数据集,这非常难看,也非常容易出错)。在这里,任何其他在开始时没有此类调用的测试都将照常使用测试用例数据集
  • 您可以在通用(测试用例)数据集的基础上构建测试数据集。如果使用INSERT操作(而不是CLEAN_INSERT),它将在公共数据集中的所有行之后插入特定于测试的行。您还可以使用DELETE操作从公共数据集中删除一些不需要的行
  • 顺便说一句,即使测试用例的设置操作已经更改,不调用onSetUp()也可以实现这一点