4

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

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

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

假设我有(蹩脚的例子)代码:

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

然后是通过嘲笑来测试成功和失败的测试mysql_connect

4

2 回答 2

4

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

不容易测试的是它们所代表的依赖关系。您通常不会注入这些资源,而是围绕这些资源编写代码。我们称之为面向对象反转。

Central 是对象(资源),以过程风格属于它的代码始终具有该资源的依赖关系。我们以 curl 为例:

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

由于围绕$handle对象的这种程序风格,如果 curl 是某些其他代码的依赖项,则在某种意义上用模拟替换功能是不可模拟的。因此,您需要先将其包装以使其可注射:

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

于 2012-04-13T00:04:00.463 回答
1

这可能会帮助那些试图模拟像 Curl 这样的 PHP 函数的人: https ://github.com/IcecaveStudios/isolator

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

于 2016-01-28T21:39:09.350 回答