用于单元测试的模拟php资源类型

时间:2012-04-12 23:48:32

标签: php unit-testing phpunit

我必须为使用由我们使用的apache扩展创建的资源类型的php类编写测试,但是假设它是具有mysql资源类型的数据库类。

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

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

让我说我有(蹩脚的例子)代码:

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

然后通过模拟mysql_connect来测试成功和失败的测试。

2 个答案:

答案 0 :(得分:4)

也许你有点远。实际上,用PHP测试资源是完全没问题的,你可以得到他们的类型等等。

不容易测试的是它们所代表的依赖关系。你通常不注入那些,但你围绕这些资源编码。我们称之为反向导向的对象。

Central是对象(资源),在过程样式中属于它的代码始终具有该资源的依赖性。我们以curl为例:

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

作为围绕$handle对象的这种程序风格,如果curl是某些其他代码的依赖关系,那么在某种意义上用mock替换功能是不可模仿的。因此,您需要先将其包装起来以使其可注射:

$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扩展的情况下,它是错误处理。但是它仍然越来越近,如果记录缺陷,这也有帮助。

答案 1 :(得分:1)

这可能会帮助那些试图模仿PHP函数的人,比如Curl:https://github.com/IcecaveStudios/isolator

它允许您将它们与代码隔离开来,使您能够使用正常的模拟技术。