PHPUnit类中的mock / stub功能

时间:2011-11-10 09:22:20

标签: php unit-testing mocking phpunit stub

我需要一些关于如何处理这个问题的建议。

使用PHP 一个例子是:

class BuilderClass {
 function getClass($id, $some, $vars){
  $dbResult = new db_Class::getDbRows($id, $some, $vars);
  foreach(...)
   // Build something from the database values

  return self;
 }
}

所以我想做的是创建一个测试用例,我以某种方式模拟db结果。

我没有找到任何好方法来做到这一点,请指出我正确的方向或类似的方式让我的工作。

我可以在构建器本身中更改某些内容,例如调用运行该函数的类:FunctionRunner :: runStaticFunction(“db_Class”,“getDbRows”,$ args,$ something_else);但目前我不知道这是否可能。任何涉及此或任何解释此问题的网站的研究文章。我现在正在做任何事情。

由于 /马库斯

3 个答案:

答案 0 :(得分:3)

拆分从数据库检索数据和构建数据的操作。

class BuilderClass {
    function getClass($id, $some, $vars){
        $dbResult = new db_Class::getDbRows($id, $some, $vars);
        return doGetClass($dbResult);
    }

    function doGetClass($dbResult) {
        foreach(...)
         // Build something from the database values

        return self;   
    }
}

这样,您可以独立于调用数据库来测试doGetClass

答案 1 :(得分:1)

通常情况下,无法轻松编写功能测试是由应用程序设计中的缺陷引起的。在这种情况下,db_Class与BuilderClass紧密耦合。

一个合适的解决方案是使用依赖注入在BuilderClass中拥有一个Database对象,并模拟该注入以返回静态结果。

class BuilderClass
{
    protected $oDatabase;
    public function __construct(db_Class $oDatabase) {
        $this->oDatabase = $oDataabse;
    }

    public function getClass($someVars) {
        $this->oDatabase->getDbRows($someVars);
    }
}

这样,Database对象很容易被stub替换。

答案 2 :(得分:0)

有很多方法可以做到这一点,但由于我们在谈论PHP,你可以利用magic class loader function

简单地说,如果你想模拟数据访问层,你只需创建一个具有数据类实际名称的对象,永远不会调用自动加载器。

想要实际访问数据库?不要定义类,当某些东西试图访问数据库时,将调用自动加载器,然后应该知道如何加载该类。

当我使用它们时,我的自动装载机往往看起来像这样;

function __autoload($className)
{
  if(file_exists('../includes/'.$className.'.php'))
    require_once('../includes/'.$className.'.php');
}