【问题标题】:phpunit database testing without affecting the databasephpunit数据库测试不影响数据库
【发布时间】:2015-08-18 10:57:55
【问题描述】:

我使用 phpunit 已经有几天了,到了需要测试数据库查询的地步。我遵循了 phpunit 官方文档,但我认为我错过了它背后的主要思想。我像这样实现了getConnectiongetDataSet这两个抽象函数:

  /**
   * @return PHPUnit_Extensions_Database_DB_IDatabaseConnection
   */
  public function getConnection()
  {
      $pdo = new PDO('mysql:host=localhost;dbname=testdb', $this->config['mysql_usr'], $this->config['mysql_pass']);

      return $this->createDefaultDBConnection($pdo, 'testdb');
  }

  /**
   * @return PHPUnit_Extensions_Database_DataSet_IDataSet
   */
  public function getDataSet()
  {
      return $this->createXMLDataSet(dirname(__FILE__).'/../dbTest/fixtures/data.xml');
  }

好吧,现在我正在与我的本地数据库进行交互,但是为什么我需要创建 XML 数据集(除了比较之外,我还需要它吗)? 我发现自己只与数据库中的数据进行交互。 例如,现在我想测试一个从数据库中删除的函数:

  function deleteRule($id){
    $DBH = $this->getDbh();

    $query = "SELECT id from ads where group_id=$id";
    $STH = $DBH->query($query);
    if ($STH->rowCount() > 0){
      throw new Exception("Rule has {$STH->rowCount()} ads, can't delete", 400);
    } else {
      $query = "DELETE FROM rules WHERE id=:id limit 1";
      $stmt = $DBH->prepare($query);
      $stmt->execute(array(':id' => $id));
    }
  }

所以我开始为它编写一些测试,其中一个看起来像这样:

public function testDeleteRule_legalDeletion()
{
  $id = 3;
  $pdo = $this->getConnection();
  $fixture = new AdRules();
  $fixture->setDbh($pdo);
  $res = $fixture->deleteRule($id);

  $DBH = $fixture->getDbh();

  $query = "SELECT * FROM rules WHERE id=3";
  $stmt = $DBH->prepare($query);
  $stmt->execute();
  $rows = $stmt->rowCount();

  $this->assertEquals($rows,0);

}

但是现在,从数据库中删除后,我怎样才能将其恢复到初始状态?我知道我可以简单地执行 mysql 语句,但我猜它错过了模拟 PDO 对象和避免数据库中的重大更改的所有要点。 无论如何,我对此感到非常困惑,任何指导将不胜感激,谢谢。

【问题讨论】:

    标签: php database phpunit


    【解决方案1】:

    建议使用其他数据库进行测试,因为您可以按照您的说法破坏您的生产数据。当您有其他数据库时,您可以使用事务机制来测试您的查询。

    这是如何工作的?

    1. 在引导测试中,您应该连接到您的测试数据库
    2. PHPUnit 调用 setUp 启动在引导程序中创建的数据库句柄上的新事务
    3. 然后在您的测试用例 (testDeleteRule_legalDeletion) 中修改数据库内容并断言数据符合您的预期
    4. PHPUnit 调用 tearDown 方法回滚事务并清理您的表(用于测试数据库句柄)

    因此,对于这些操作,您可能需要一些通用的数据库测试用例,例如DbTransactionalTestCase,在这个类中你必须重写方法setUptearDown

    附言。如果您对自动化此过程的框架感兴趣,请查看我们如何在Ouzo Framework 中执行此操作。 Here 是您的问题的文档。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-20
      • 1970-01-01
      • 2011-10-17
      相关资源
      最近更新 更多