【问题标题】:mock php's resource type for unittesting用于单元测试的模拟 php 资源类型
【发布时间】:2012-04-12 23:48:32
【问题描述】:

我必须为使用由我们使用的 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

【问题讨论】:

    标签: php unit-testing phpunit


    【解决方案1】:

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

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

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

    【讨论】:

    • 我看不到你的意思......如果我要测试这个类,并且在 curl_exec 之前它检查资源的类型是原始的 curl 类型怎么办?而且我不希望它使用真正的 curl 函数?
    • @gcb: 你要么想对Curl 类进行单元测试(当你这样做时,句柄是内部的,不需要测试)或者你想测试一些其他组件使用 Curl 类,那么你可以给它一个模拟 Curl 类。
    • 如果我正在测试Curl 类,那么我如何避免访问网络服务器并出现不一致?
    • @gcb:你什么意思?你要么想测试它与网络服务器的集成,要么你不想。所以你假设它有效,所以你可以模拟它。或者你预计它会失败,所以你也嘲笑它。
    • 例如,您可以让Curl 抛出异常:if (! $this->handle = curl_init($url)) throw new Exception('Failed to initialize.');。然后,您不需要依赖内部状态(句柄)。 Curl 类型将发出信号,如果它不能做它想做/需要做的事情。
    【解决方案2】:

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

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-02
    • 1970-01-01
    • 2021-11-05
    • 2016-09-20
    • 1970-01-01
    相关资源
    最近更新 更多