2012-04-12 43 views
3

我必须为php类编写测试,该类使用由我们使用的apache扩展创建的资源类型,但让我们假设它是一个带有mysql资源类型的数据库类。模拟php的单元测试资源类型

显然我想嘲笑这些全局函数,但是当类检查资源是否创建好时如何伪造返回类型?

php文档中的资源页面甚至有一条评论抱怨测试无法进行模拟。这是最终的答案吗?

比方说,我有(例如瘸)代码:

class DB { 
    function init(){ 
    $this->handle = mysql_connect('myserver'); 
    if(get_resource_type($this->handle) != 'mysql') return false; 
     return true; 
    } 
} 

,然后测试对于成功和失败的考验,通过嘲讽mysql_connect

回答

4

也许你有点遥远。实际上,使用PHP进行测试的资源是非常好的,你可以得到他们的类型等等。pp ..

不容易测试的是它们所代表的依赖关系。您通常不会注入这些资源,但您可以在这些资源上编码。我们称之为对象反转导向。

中心是对象(资源)和属于它的程序样式中的代码始终具有该资源的相关性。让我们卷曲为例:

$url = 'http://example.com/'; 
$handle = curl_init($url); 
curl_exec($handle); 

由于各地$handle对象这不是在这个意义上mockable使用模拟更换功能,如果卷曲是一些其他的代码依赖这个程序的风格。所以,你需要首先把它包起来,使其注射:

$url = 'http://example.com/'; 
$curl = new Curl($url); 
$curl->exec(); 

这都与你需要的资源为中心的面向对象转换成一个普通的旧式PHP对象价格:

class Curl 
{ 
    private $handle; 
    public function __construct($url) { 
     $this->handle = curl_init($url); 
    } 
    public function exec() { 
     return curl_exec($this->handle); 
    } 
} 

这很容易现在来嘲笑它。好的是,这通常是可能的,所以通常资源本身不应该对测试施加任何限制,它只是一些缺少的封装,所以您需要先添加它。

由于全局静态状态,某些API(如imap扩展名)不允许创建干净的对象接口,如果是IMAP扩展名,则是错误处理。但是它仍然越来越接近,如果缺陷被记录下来,那也是有帮助的。

+0

我没有看到你指向...如果我要测试这个类,并且在curl_exec之前检查资源的类型是原始卷曲类型?我不希望它使用真正的卷曲功能? – gcb 2012-04-13 17:27:25

+1

@gcb:你可能要单元测试'Curl'类(当你这样做时,句柄是一个内部的,不需要测试),或者你想测试一些其他使用Curl的组件'类,那么你可以给它一个'Curl'类的模拟。 – hakre 2012-04-13 18:02:38

+0

如果我正在测试'Curl'类,那么如何避免打击Web服务器和不一致呢? – gcb 2012-04-13 18:06:04