在PHP 7中修补猴子

时间:2016-11-14 21:51:17

标签: php mocking phpunit

这个four year old question使用的第三方图书馆,我有点怀疑。

仅出于测试目的,我想重新定义其中一个类的静态方法。请看以下示例:

class Driver {
   public static function getVersion() : string
   {
        // Retrieves a version from a system executable
        return some_system_call();
   }
}

class Module {
   public function methodToTest()
   {
       if (Driver::getVersion() === '4.0.0') {
          // allow for additional options/methods
       } else {
          // use a subset
       }
   }
}

我需要让Driver::getVersion返回不同的版本字符串。我通常会嘲笑这个课程,但由于这既没有注入,也没有实例,所以它无法发挥作用。

我可以更改源代码,添加方法和属性测试,以便正在测试的类永远不需要调用Driver,但在我看来,重构代码只是为了进行测试"工作"不是解决方案。

我正在思考创建另一个Driver类并以某种方式加载它来代替原始类。

我该怎么做?

3 个答案:

答案 0 :(得分:2)

你可能想要使用像:

class Module
{
   private $version;

   public function __construct($version){
      $this->version = $version;
   }

   public function methodToTest()
   {
       if ($this->version === '4.0.0') {
          // allow for additional options/methods
       } else {
          // use a subset
       }
   }
}

或其他选项是注入不是版本而是注入提供者(如果你知道你将有一些复杂的版本控制逻辑 - 所以你可以在Module和{{1}之间分割逻辑酌情):

Provider

还有一个可能正在实现一些代理类,如

class Module
{
   private $versionProvider;

   public function __construct($provider){
      $this->versionProvdier = $provider;
   }

   public function methodToTest()
   {
       if ($this->versionProvider->getVersion() === '4.0.0') {
          // it could be even $this->versionProvider->newFeaturesAreSupported()
       } else {
          // some other stuff
       }
   }
}

所以你可以单独模仿你的monostate(可能是通过反对私有或通过它的公共界面,反正不要忘记class Module { public function methodToTest() { $myMonostateProxy = new MyMonostateProxy(); $version = $myMonostateProxy->getVersion(); if ($version === '4.0.0') { // allow for additional options/methods } else { // use a subset } } } 它)。真正实现它只会称之为无法控制的tearDown

我认为前两个选项更清晰,但需要一些努力来创建(因为你需要一些注射来执行)。 第三个具有隐藏的依赖性,在测试中有点棘手,因此不太干净,需要更多的维护工作,但隐藏了所有选择内容,使常规使用更容易。

答案 1 :(得分:0)

class Driver {
    private static $testVersion;

    public static function setTestVersion(string $testVersion = null)
    {
        static::$testVersion = $testVersion;
    }

    public static function getVersion() : string
    {
        if (static::$testVersion !== null) {
            return static::$testVersion;
        }
        // Retrieves a version from a system executable
        return some_system_call();
    }
}

答案 2 :(得分:0)

您可以注册一个类加载器,它以某种方式了解测试并从其他位置加载修改过的Driver类。