2009-05-03 67 views
2

當我理解單元測試與另一個對象(「有一個」關係)有構成關係的對象時,如果您正在使用某種類型的依賴注入,您只能真正地模擬組合對象。因此,下面的代碼種類化妝單元測試非常困難的,並且可能因此被認爲是壞的事情:沒有依賴注入的對象組合是壞事嗎?

<?php 
class aSampleClass { 
    private $dependency; 
    public function __construct() { 
     $this->dependency = new otherClass; 
    } 
} 

該玩具例子很容易通過使otherClass對象的實例作爲一個參數轉換爲使用依賴注入到構造函數,但情況並非總是如此。上述形式的對象組合(其中「新」運算符直接用於類實現中)是一件壞事?你是否應該總是試着寫一個班級,以便它能夠完全獨立於其關聯進行測試?

使用依賴注入似乎當您使用簡單的值對象(在領域驅動設計的說法),如日期或貨幣對象爲我擱淺。在這些情況下,直接實例化有問題的Value對象似乎是有意義的。例如:

<?php 
    class anotherSampleClass { 
     public function getTimeDifferencePhrase() { 
      $now = new date_Time; 
      $then = new date_Time(time()-60*60*24); 
      return $now->relativeTimePhrase($then); 
     } 
    } 

當然,在這個例子中,它使的anotherSampleClass單元測試更有意義,也鍛鍊了date_Time對象的實現,而不是試圖使用模擬對象或測試雙打。

想法?

回答

0

在這些情況下應該沒有明確的規則。依賴注入通常是一件好事,但並不總是必需的。這是關於分析你的班級,並確定誰應該真正負責創建依賴關係。

如果你與,語義,屬於你的類和你的類是他們完全負責很簡單的對象時,則依賴注入可能是過度工程。你真的不需要測試date_Time,所以我不打擾注入特定的依賴。

要考慮的另一件事是,構造函數中構建的依賴關係是否可能使您的類無法測試。例如,它發生在使用隨機數發生器的類中。在這種情況下,如果你不使用依賴注入,那麼真的沒有辦法注入一個生成器,它會給你一組可預測的適合測試的數字。

所以,簡短的回答:這通常是一件好事,但並不總是必要的。

0

對於這樣的事情沒有硬性規定。一些純粹主義者會說你應該注入依賴,而另一些則會採取更實際的方法。由於VO本身本身沒有任何依賴關係,因此我可能會調用KISS原則,並且說在對象中「新」它是完全正確的。尤其是,VO駐留在同一個模塊中(按照DDD的術語)。此外,在對象中實例化VO並不會降低其可測性。

1

這取決於你正在測試什麼。依賴注入解決了測試你的類的問題,而不必擔心它對外部服務的依賴(可能失敗,沒有測試數據,或者不適合單元測試)。

你不會嘲笑值對象(或字符串,INT等)只是爲了測試你的類構建正確,並稱爲差分算...這是執行的一部分,是不是真的與測試相關。

但是,如果通過60 * 60 * 24 seconds,您將會測試您的getRelativeTimeDifferencePhrase正確返回「24小時前」。

然後你會意識到你的硬編碼time()會導致一個脆弱的測試 - 因爲你無法準確預測time()在代碼運行時會返回什麼。這將導致一個RealTimeService,這將引入一個可以控制的接縫。

有你的類實例化一個RealTimeService會讓你沒辦法注入你MockTimeService - 這樣就可以硬編碼它是什麼time(),所以你那麼最終會傳遞一個ITimeService到你的構造。現在,你有依賴注入。 ;)

1

依賴注入確實解決了很多問題。但是,很多人沒有看到它是一種聚合而不是組合。在您實例化otherClass的示例中,您有一個構圖。因此,通過引入依賴注入,你真的打破了德米特的組成和法則,並引入了聚合。

我認爲依賴注入很好,只要它不破壞體系結構。很多人都說在構造函數中使用new運算符是不好的,而應該將一個實例傳遞給構造函數,但它們是錯誤的。它應該取決於域。有些情況甚至會導致混淆,特別是在沒有垃圾回收的語言中。例如,C++中的經驗法則是創建者銷燬一個對象。所以如果有電池的手機被銷燬了,誰會摧毀電池?電話或任何對象傳遞給電話?但在某些情況下,您會希望將電池放入電話。例如,如果你正在建模工廠。

因此,回答你的問題「沒有依賴注入的對象組合是一件壞事嗎?」 - 這取決於你正在建模的領域,在可測試性上犧牲設計是IMO的一個壞事。如果你發現一些不可測試的東西,那麼看看你的設計是否正確。我通常會看到是否可以引入依賴注入。如果沒有問題,那麼我看我是否可以引入工廠方法。如果不是,我會看看我能否做點別的。