2

我有以下代码:

<?php

class X
{
    public function do($url)
    {
        $httpRequest = new \HttpRequest\Curl($url, $this->getOptions());
        $httpRequest->fire();
        // etc.
    }
    // ...
}

为了能够对这个类进行单元测试,我想注入一个模拟的 HttpRequest 类。一种方法如下:

<?php

class X
{
    private $httpRequestClass;

    public function __construct($httpRequestClass = '\HttpRequest\Curl')
    {
        $this->httpRequestClass = $httpRequestClass;
    }

    public function do($url)
    {
        $httpRequest = new $this->httpRequestClass($url, $this->getOptions());
        $httpRequest->fire();
        // etc.
    }
    // ...
}

但这似乎不对。还有其他想法吗?

4

2 回答 2

1
 public function __construct($url, $httpRequestClass = null)
    {
        $this->url = $url;
        if ($httpRequestClass == null) //> Default
           $this->httpRequestClass = new HttpRequest\Curl($this->url);
        else
           $this->httpRequestClass = $httpRequestClass;
    }

因此,当您通常使用此类时,只需使用一个参数调用它

yourClass('your url');

否则在第二个参数中传递 istance

yourClass('url', new MockedObj);

当然,您应该始终在不提供默认对象的情况下注入您的依赖项

于 2012-10-16T17:00:14.203 回答
0

该类需要生成 HttpRequest 类型的对象,但我们不一定希望它初始化一个对象:例如,我们可能希望它使用原型模式。因此,该类需要工厂模式。为简洁起见,我选择了工厂回调,而不是工厂类。

<?php

class X
{
    private $factoryCallback;

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

    public function do($url)
    {
        $httpRequest = $this->createHttpRequest($url);
        $httpRequest->fire();
        // etc.
    }

    private function createHttpRequest($url)
    {
        $callback = $this->factoryCallback;
        if (is_callable($callback)) {
            return $callback($url, $this->getOptions());
        }
        return new \HttpRequest\Curl($url, $this->getOptions());
    }
    // ...
}

在这个例子中,辅助方法 ,createHttpRequest()有点多余,但可以用于生产代码中的错误处理。

于 2012-10-21T13:39:44.887 回答