2012-10-16 87 views
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. 
    } 
    // ... 
} 

但這看起來不對。任何其他想法?

回答

0

類需要生成OB例如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(),在該示例中有點冗餘,但是將被用於在生產代碼處理錯誤。

+0

你能解釋一下你爲什麼要選擇這個選項,如何比其他答案中的方法更好? – raina77ow

+0

是的,你說得對 - 我沒有解釋。幹得好。 – moteutsch

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; 
    } 

所以,當你使用這個類通常只是一個PARAM稱之爲

yourClass('your url'); 

否則通過istance在第二個參數

yourClass('url', new MockedObj); 

當然,你應該總是注入你依賴不提供一個默認的對象

+0

看看我編輯過的帖子。 – moteutsch

+0

同樣的答案有 – dynamic

+0

+1 - 你應該總是注入你的依賴無需證明默認對象 – AlexP