单元测试PHP框架

时间:2013-08-24 07:56:31

标签: php unit-testing

我有一个我们公司使用的自定义轻量级PHP框架。首先,我不希望该建议使用第三方框架。我正在尝试为它编写单元测试,但我偶然发现了一个问题。我对单元测试比较陌生,但大部分代码已经被覆盖了。

我有一个加载器类,需要无法使用类自动加载器加载的文件(例如配置文件)。它有一种回退系统,如果你没有指定一个模块来加载特定的资源,它将尝试根据当前模块进行猜测,然后是默认模块。这要求我(据我所知)在回到默认值之前检查特定文件是否存在。

我遇到的问题是为该类编写测试,该测试实际上并不依赖于任何现有文件(这显然是可取的)。我读过关于虚拟文件系统和测试的内容,但我很难看到如何利用它来解决我的问题。

我可以写一个我注入这个类的文件系统的抽象,但那个类会遇到类似的问题。

在伪代码中:如果该模块中存在文件,则加载它;如果没有,请加载默认值。

非常感谢任何建议。

编辑:

以下是代码的摘录:

class Base implements Loader {

...

protected function _include( $type, $name ){
    $identifier = $this->parseName($name);

    $path = '/'.$this->resource_types[$type]['directory'].'/'.$this->resource_types[$type]['file_prefix'].$identifier['name'].'.php';

    if( $identifier['module'] && is_file(Core::basePath().'/'.Constant::get('MODULE_PATH').'/'.$identifier['module'].$path) ){
        Core::requireRoot('/'.Constant::get('MODULE_PATH').'/'.$identifier['module'].$path);

    } else if( is_file(Core::basePath().'/'.Constant::get('CORE_PATH').$path) ){
        Core::requireRoot('/'.Constant::get('CORE_PATH').$path);

    } else {
        throw new Exceptions\Load(ucwords($type).' '.$name.' not found');
    }
}

....

}

这是一个非常低级的类,因此它有一些静态调用,基本上是本机PHP函数的替代或包装。 Core::requireRoot只是本机require函数的包装器。 Constant::get是常量的自定义实现(define的替代,然后直接使用常量)。请记住,我实际上并没有直接测试这种方法。我有公共方法,例如loadHooks,我实际上正在测试它在幕后调用这个方法。

1 个答案:

答案 0 :(得分:1)

感谢@ hek2mgl和(在较小程度上)@deceze(我的静态调用是正确的),我有一个解决这个问题的方法。它不是我原本希望的那种解决方案,但我认为这是最好的。到此为止。

我将使用临时文件,根据@ hek2mgl的建议(github.com/metashock/Jm_Autoloader)。即使使用文件系统抽象对象,我也认为没有办法解决这个问题。也就是说,我将使用我将注入此类的文件系统抽象对象,因为它将更容易在其他上下文中重用临时文件替换。

我将删除该函数中的静态调用(我知道这比做的更好,但是很容易让自己相信“这是一个低级别的类,它实际上并不重要”)。相反,我将为CORE_PATH和MODULES_PATH创建getter和setter方法,并恢复为require的本机调用。这不需要使用新的文件系统对象,但我认为它更清晰,更灵活,更松散耦合。