2013-05-28 38 views
0

免责声明:是的,我已经阅读了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))的可迭代对象。

这种方法显然有两个责任:第一个从外部数据源获取原始数据,第二个将原始数据重新排列到最终结果。我知道它应该以某种方式分开。

  1. 数据库接口使用工厂方法,该方法返回带有可链式方法的对象。这是嘲弄的噩梦。我开始为CDbCommand和创建CDbConnection的CDbConnection编写手动伪造代码,但是我已经编写了很多代码,可能需要它自己的单元测试。我完全不理解我应该如何嘲笑对数据库的请求。
  2. 这段代码只是一个例子。我有很多类似的方法,但他们中的很多人不是一次调用数据库,而是多次调用数据库,所以“获取原始数据,重新格式化”可能不是这里的模式,但我不确定。

最后:我正在测试在这里受相关PHPUnit的测试方法的名称描述:

public function CanFindNumberOfOrdersGroupedByStatus() 
为什么我在这里停留

主要的原因是什么,我测试基本上是是否SUT能成功从持久性存储获得一些统计数据,就这些了。与数据库的所有交互都是实现细节,但在我使用的遗留代码中,它是连接持久性存储的唯一方式(使用上面的CDbCommand/CDbConnection组合),而这个持久性存储是MySQL数据库。

我想知道我是否需要实现CDbConnection的完整后端,它将使用内存中的灯具而不是真正的数据库来正确地对这些方法进行单元测试。

是的,防止可能的问题,项目政策禁止在Yii框架中内置的ActiveRecords的使用。

+1

设置一个单独的测试数据库,并简单地测试已知结果? –

+0

@IvoRenkema男人,我在这里谈论'单位'测试。整个问题是**而不是**使用真正的数据库,否则每个人都知道如何测试这样的功能。 – hijarian

回答

-1

你不需要编写太多的代码来测试它。 Yii拥有出色的测试框架,包括数据库测试和数据库夹具功能,将完美覆盖这一传统功能。

为了您阅读:

Testing in Yii(见章节对灯具内)

一般来说,你会到底是什么了做是:

  1. 设置测试配置和测试引导文件规定在指南中(默认示例应用程序将包含示例测试配置/引导程序设置)。
  2. 用模式创建测试数据库并指向您的测试配置。
  3. 撰写一个延伸CDbTestCase的课程。这只是您的普通PHPUnit测试,Yii的特殊附加功能使测试更容易。如果您对PHPUnit不熟悉,请参阅the docs
  4. 根据Yii指南为您的测试数据库编写一些灯具。这可确保测试数据库的测试数据。
  5. 编写按原样调用Order类的函数并像在普通单元测试中一样声明结果的测试。 (此代码单元测试CDbTestCase子类的内部):

    $这 - >的assertEquals( 阵列(1 => 2,2 => 5), 订单::模型() - > getOrderCountGroupedByStatus() );

+0

我已经回答了一位评论者,对你的回答同样如此:我既不需要也不想提升整个MySQL实例,并实例化Yii应用程序来测试这个函数。我想要**单元**测试,而不是集成测试。谢谢,我完全知道如何设置与Yii的数据库测试,在那里,做到了。 – hijarian