php - 如何在单元测试中捕获无效查询错误

标签 php mysql database unit-testing mocking

我几个月前在我们的开发过程中引入了单元测试。

我刚遇到这个问题:我为一个简单的函数编写了一个测试用例,并依赖于数据库查询。我使用模拟对象而不是数据库适配器对象。测试通过,到目前为止一切顺利。

但这是误报。模拟对象从数据库返回了预期的结果集(它必须,因为它是模拟对象),但由于拼写错误,真正的查询没有返回有效的结果集。

我可以解决这个问题的一种方法是在查询没有产生记录集时抛出异常。

$db->query($query);
$resultset = $db->fetchAll();
if(!is_array($resultset)) throw new UnexpectedValueException("Query does not yield a result set");

这种做法只会让整个脚本失败(如果没有捕获到异常),测试肯定会失败。

我的问题是:这是正确的方法吗,或者您会推荐其他方法吗?

最佳答案

IMO 你的方法是错误的。为什么?

  1. 您没有测试模型能否正确使用数据库(例如插入、更新或删除记录、选择记录)。

  2. 您无法检查查询是否正常。

我们如何做到这一点?

我们使用迁移系统 ( https://github.com/ruckus/ruckusing-migrations ) 让我们可以轻松更改数据库。我们的系统有两个数据库 - 用于生产和测试。

当我们创建新更改(例如,使用一些更改列)时,我们会运行将更改应用到这些数据库的迁移。

在测试中,我们使用每次测试后回滚的事务。你可以看看这个 - https://github.com/letsdrink/ouzo/blob/master/src/Ouzo/Core/Tests/DbTransactionalTestCase.php (这是我们的框架)如您所见,有覆盖方法 setUptearDown,它们在每次测试后启动和回滚事务。您应该编写一个集成测试。

这是如何工作的?

具体可以找example here .

public function shouldPersistModel()
{
    //given
    $product = new Product();
    $product->name = 'Sport';

    //when
    $id = $product->insert();

    //then
    $this->assertNotNull($id);
    $actual = Product::findById($id);
    $this->assertEquals('Sport', $actual->name);
}

工作流程:

  1. 运行方法 setUp 开始交易。
  2. 创建对象 Product 并插入到数据库中。
  3. 获取具体对象。
  4. 断言。
  5. 运行方法 tearDown 将数据库回滚到以前的状态。

这里是 link to the docs .

关于php - 如何在单元测试中捕获无效查询错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28150297/

相关文章:

mysql - 删除巨大 MySQL 表的最快方法

php - 如何知道什么值从我的 Activity 发送到 Android 中的 MySql 服务器

database - 使用 JSON 的离线数据库文件系统。使用一个或多个文件

database - 创建具有最大行数的表 (ORACLE)

node.js - nextjs做一个API请求正常吗?

php - 使用 PHP 检查 MYSQL 上的 TIME 字段

python - 带增量字段的 LOAD DATA LOCAL INFILE

php - 使用 PHPStorm 使用 XDebug 调试 Codeigniter

php - 使用数组的 PDO bindParam,未按假设工作

php - 我可以使用 Delphi 写入 BDE 并使用 PHP 读取它吗?