免责声明:是的,我已经阅读了FAQ,并在Stackoverflow的边界内考虑了这样一个问题。不,我不知道如何正确命名它。 :(如何进行单元测试并重构此PHP函数?
我的问题很简单:如何单元测试下面的方法和我应该做的重构,使之可测试我再说一遍:我不想要求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 framework PHP应用程序。
$this->db
是一个CDbConnection对象。 $this->db->createCommand()
返回一个CDbCommand对象。
CDbCommand.queryAll()
返回在每次迭代时发出数组array('status' => (string), 'count_status' => (int))
的可迭代对象。
这种方法显然有两个责任:第一个从外部数据源获取原始数据,第二个将原始数据重新排列到最终结果。我知道它应该以某种方式分开。
- 数据库接口使用工厂方法,该方法返回带有可链式方法的对象。这是嘲弄的噩梦。我开始为CDbCommand和创建CDbConnection的CDbConnection编写手动伪造代码,但是我已经编写了很多代码,可能需要它自己的单元测试。我完全不理解我应该如何嘲笑对数据库的请求。
- 这段代码只是一个例子。我有很多类似的方法,但他们中的很多人不是一次调用数据库,而是多次调用数据库,所以“获取原始数据,重新格式化”可能不是这里的模式,但我不确定。
最后:我正在测试在这里受相关PHPUnit的测试方法的名称描述:
public function CanFindNumberOfOrdersGroupedByStatus()
为什么我在这里停留
主要的原因是什么,我测试基本上是是否SUT能成功从持久性存储获得一些统计数据,就这些了。与数据库的所有交互都是实现细节,但在我使用的遗留代码中,它是连接持久性存储的唯一方式(使用上面的CDbCommand/CDbConnection组合),而这个持久性存储是MySQL数据库。
我想知道我是否需要实现CDbConnection的完整后端,它将使用内存中的灯具而不是真正的数据库来正确地对这些方法进行单元测试。
是的,防止可能的问题,项目政策禁止在Yii框架中内置的ActiveRecords的使用。
设置一个单独的测试数据库,并简单地测试已知结果? –
@IvoRenkema男人,我在这里谈论'单位'测试。整个问题是**而不是**使用真正的数据库,否则每个人都知道如何测试这样的功能。 – hijarian