免责声明:是的,我已经阅读了常见问题解答,并在 Stackoverflow 的范围内思考了这样一个问题。不,我不知道如何正确命名它。:(
我的问题很简单:如何对以下方法进行单元测试以及我应该进行哪些重构以使其可测试?我再说一遍:我不想让 DB 和 Yii 应用程序实例四处飘荡来测试这个功能。
public function getOrderCountGroupedByStatus()
{
$arr = $this->db->createCommand()
->select('COUNT( status ) AS count_status, status')
->from('order_item')
->group('status')
->order('status')
->queryAll();
$orderItemsCountByStatus = array();
foreach($arr as $os)
$orderItemsCountByStatus[(int)$os['status']] = $os['count_status'];
return $orderItemsCountByStatus;
}
这是通过手动测试整个应用程序来检查有效性的遗留代码。
它来自基于Yii 框架的 PHP 应用程序。
$this->db
是一个CDbConnection对象。$this->db->createCommand()
返回一个CDbCommand对象。
CDbCommand.queryAll()
array('status' => (string), 'count_status' => (int))
返回可迭代对象,该对象在每次迭代时发出一个数组。
这种方法显然有两个职责:第一个从外部数据源获取原始数据,第二个将原始数据重新排列为最终结果。我知道它应该以某种方式分开。
- 数据库接口使用工厂方法,该方法返回具有可链接方法的对象。这是一个可以嘲笑的噩梦。我开始为 CDbCommand 和创建它的 CDbConnection 编写手动伪造,但我已经编写了很多代码,它可能需要它自己的单元测试。我完全不明白我应该如何模拟对数据库的请求。
- 此代码只是一个示例。我有很多类似的方法,但是很多都不是一次调用数据库,而是多次调用,所以“获取原始数据,重新格式化”可能不是这里的模式,但我不确定。
最后:我在这里测试的是相关 PHPUnit 测试方法的名称:
public function CanFindNumberOfOrdersGroupedByStatus()
我卡在这里的主要原因是我测试的基本上是SUT是否可以成功地从持久性存储中获取一些统计信息,仅此而已。与数据库的所有交互都是这里的实现细节,但在我正在使用的遗留代码库中,它是连接到持久性存储的唯一方法(使用上面的 CDbCommand/CDbConnection 组合),这个持久性存储是 MySQL 数据库。
我想知道我是否需要为 CDbConnection 实现完整的后端,它将与内存中的装置而不是真实的数据库一起使用,以正确地对这些方法进行单元测试。
是的,为了避免可能的问题,项目政治禁止使用 Yii 框架中内置的 ActiveRecords。