模拟在PHP中使用静态方法创建的对象的函数?

时间:2012-03-23 20:12:26

标签: php unit-testing phpunit

我正在使用ORM,而我获取记录对象的方式是使用FooModel::find(1)FooModel有一个我需要模拟测试的方法。我该怎么做? (不能使用PHPUnit mock因为这会给我一个模拟的FooModel,它与ID 1的记录不对应。)

修改

示例:

class FooModel
{
    // ORM model that fetches record from the DB

    public function thisNeedsToBeMocked()
    {
        // some code here that depends on external factors so should be part of unit tests
    }
}

我获取ID为1的记录的方式是:

$fooObject = FooModel::find(1);

我需要能够在运行thisNeedsToBeMocked()方法$fooObject之后模仿我static find()

1 个答案:

答案 0 :(得分:0)

您遇到了经典的单元测试问题。您用于静态调用的类名是全局命名空间的一部分。这意味着您无法插入模拟。这不是你可以在这里做的魔术,要解决这个问题,你将不得不做一些代码更改。

有许多方法可以解决这个问题,并且有许多方法可以解决这个问题。我会给你一个简单的黑客解决方案。如果你想要一些不同的东西让我知道,我会编写一个例子。

我还假设您无法将ORM更改为基于静态类。

这是黑客的方法,这是一种非常糟糕的做事方式,所以你知道。在类中有一个变量,它是您需要使用的ORM类的类名。这是PHP 5.3代码。

像这样:

<?php

class Bar {
    public static $ormName = 'FooModel';

    public static function doStuff()
    {
        $className = self::$ormName;
        echo $className::find(1), "\n";
    }
}

然后在您的PHPUnit测试中创建一个模拟。获取它的类名,在测试主题上设置该类名。现在,您的测试对象将调用您的模拟。

有很多方法可以解决这个问题,但有些方法需要一种不直接使用类名的方法。