我几个月前在我们的开发过程中引入了单元测试。
我刚遇到这个问题:我为一个简单的函数编写了一个测试用例,并依赖于数据库查询。我使用模拟对象而不是数据库适配器对象。测试通过,到目前为止一切顺利。
但这是误报。模拟对象从数据库返回了预期的结果集(它必须,因为它是模拟对象),但由于拼写错误,真正的查询没有返回有效的结果集。
我可以解决这个问题的一种方法是在查询没有产生记录集时抛出异常。
$db->query($query);
$resultset = $db->fetchAll();
if(!is_array($resultset)) throw new UnexpectedValueException("Query does not yield a result set");
这种做法只会让整个脚本失败(如果没有捕获到异常),测试肯定会失败。
我的问题是:这是正确的方法吗,或者您会推荐其他方法吗?
最佳答案
IMO 你的方法是错误的。为什么?
您没有测试模型能否正确使用数据库(例如插入、更新或删除记录、选择记录)。
您无法检查查询是否正常。
我们如何做到这一点?
我们使用迁移系统 ( https://github.com/ruckus/ruckusing-migrations ) 让我们可以轻松更改数据库。我们的系统有两个数据库 - 用于生产和测试。
当我们创建新更改(例如,使用一些更改列)时,我们会运行将更改应用到这些数据库的迁移。
在测试中,我们使用每次测试后回滚的事务。你可以看看这个 - https://github.com/letsdrink/ouzo/blob/master/src/Ouzo/Core/Tests/DbTransactionalTestCase.php (这是我们的框架)如您所见,有覆盖方法 setUp
和 tearDown
,它们在每次测试后启动和回滚事务。您应该编写一个集成测试。
这是如何工作的?
具体可以找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);
}
工作流程:
- 运行方法
setUp
开始交易。 - 创建对象
Product
并插入到数据库中。 - 获取具体对象。
- 断言。
- 运行方法
tearDown
将数据库回滚到以前的状态。
这里是 link to the docs .
关于php - 如何在单元测试中捕获无效查询错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28150297/