2012-01-20 136 views
3

我目前正在嘗試改進用Java編寫的遺留系統的可測試性。目前最爲棘手的問題是存在無法嘲笑的「內部」依賴關係。解決這個問題非常簡單:引入依賴注入。使用構造函數注入和默認構造函數是不好的?

不幸的是,代碼庫非常大,所以在整個應用程序中引入依賴注入將是一個巨大的努力,直到「引導」。對於每個我想測試的課程,我都需要改變另外的一百個(也許我在這裏誇大了一點,但肯定會很多)類,這取決於已更改的組件。

現在我的問題:是否可以,使用兩個構造函數,默認構造函數初始化實例字段的默認值和另一個允許注入依賴關係?使用這種方法有什麼缺點嗎?它將允許依賴注入以備將來使用,但仍不需要改變現有的代碼(儘管被測試的類)。

當前代碼(「內部」的依賴):

public class ClassUnderTest { 

    private ICollaborator collab = new Collaborator(); 

    public void methodToTest() { 
    //do something 
    collab.doComplexWork(); 
    //do something 
    } 

} 

在默認/ DI構造:

public class ClassUnderTest { 

    private ICollaborator collab; 

    public ClassUnderTest() { 
    collab = new Collaborator(); 
    } 

    public ClassUnderTest(ICollaborator collab) { 
    this.collab = collab; 
    } 

    public void methodToTest() { 
    //do something 
    collab.doComplexWork(); 
    //do something 
    } 

} 
+0

這對我來說看起來很不錯。只要確保您可以使用實例字段,而不是在每次方法調用時重新實例化新實例。這兩個片段並不等同。如果必須在每個方法調用時創建新實例,則注入協作者的工廠而不是注入協作者。 –

+0

哦,你當然是對的。當我創建這個例子時,我沒有想到它。我將編輯示例。 – user1159435

+3

這被稱爲混蛋注射,並可能有問題:http://stackoverflow.com/questions/6733667/is-there-an-alternative-to-bastard-injection-aka-poor-mans-injection-via-defa –

回答

0

這是絕對正常,我這樣做偶爾也,尤其是服務式班由於遺留代碼或框架限制,缺省構造函數是必需的。

通過使用兩個構造函數,您可以清楚地分離默認協作對象,同時仍允許測試注入模擬。您可以通過使第二個構造器包受保護並將單元測試保留在同一個包中來強化意圖。

它不如完整的依賴注入模式,但這並不總是一個選項。

+0

非常感謝您的回答!我也想過要降低di構造函數的可見性。我不確定這種情況下最好的方法是什麼。公共構造函數將允許在將來使用其他依賴關係實現的情況下更容易重用(這是整個依賴注入概念背後的想法,對吧?)。你是否看到公開的缺點? – user1159435

0

我認爲這非常好。我會根據參數化構造默認構造函數,但這可能是一個風格和偏好的問題。

我會更加謹慎的是增加一個setCollaborator()函數,因爲這會徹底改變ClassUnderTest的契約(和假設),如果從某人編寫的代碼調用這將導致奇怪的錯誤場景瞭解歷史,沒有正確閱讀文檔(或者根本沒有任何文檔......)