2013-10-28 33 views
1

當重構一些代碼時,我發現我有一個創建具體類的new調用。當創建一種工廠時避免靜態方法的可測試性

我正在尋找一種避免創建具體類並提高可測試性的方法,因此我創建了一種工廠,負責返回實例。然後,我使用Spring構造函數注入,將工廠注入到被測系統中。

但是現在我面臨一個問題,就是在我的工廠中使該方法變爲靜態,同時具有良好的可測試性。據米斯科Hevery,Static Methods are Death to testability然而,我不知道該怎麼做才能刪除對新的調用,有良好的單元測試,並避免靜態方法調用。

這是使用工廠的類的摘錄。我測試在這個類中的方法利用構造(戲弄)columnFamilyTemplate的:

protected AlertFieldMatcher(ColumnFamilyTemplateBuilder columnFamilyTemplateBuilder, Keyspace keyspace, 
          T2JsonUtilInterface jsonUtil) { 
    this.columnFamilyTemplate = columnFamilyTemplateBuilder.build(keyspace, CF_ALERT); 
    this.jsonUtil = jsonUtil; 
} 



這是工廠,我現在已經在測試中嘲笑爲方法在SUT(上圖):

public class DefaultColumnFamilyTemplateBuilder 
             implements ColumnFamilyTemplateBuilder { 


    @Override 
    public ColumnFamilyTemplate<String, String> build(Keyspace keyspace, 
                 String columnFamily) { 
     ColumnFamilyTemplate<String, String> builtTemplate = 
               new ThriftColumnFamilyTemplate<String, String> 
                (keyspace, 
                 columnFamily, 
                 StringSerializer.get(), 
                 StringSerializer.get()); 
     return builtTemplate; 
    } 

    ... 
} 

我看到的唯一的選擇就是離開我的工廠類型對象的,即不使該方法是靜態的。

+2

你的代碼有什麼問題?爲什麼你要使工廠方法是靜態的?你不應該那樣做(可測試性)的原因是你可以注入*另一個工廠,它實例化一個測試對象,而不是真實的。 –

+0

我在問,因爲我沒有給我的老闆一個強有力的答案,當建議可能使其靜態。保持原樣,就像你說的(我認爲),我能夠模擬DefaultColumnFamilyTemplateBuilder並在我的測試中使用模擬實現。作爲一個靜態我想我不能那樣做。 – Crowie

+0

我也注意到我混合了一些名詞,暗示着已知的Builder模式和一個Factory對象 – Crowie

回答

1

如果您要從應用程序中刪除「新」,您需要一些代表您創建對象的機制。有三種機制可能需要檢查。

第一個是依賴注入。 DI容器允許您採用更多基於接口的方法,並選擇在運行時使用的實現。 Spring是最受歡迎的DI容器,而CDI是新的「標準」。 DI是好的,但它不一定是你想在項目後期推出的那種東西。

第二種機制是Java ServiceLoader,它允許您通過從類路徑添加和刪除文件來更改組件的實現。你可能會覺得這有點煩瑣。

最後一個機制是使用一個靜態方法(!!!!)讀入屬性,該屬性是工廠對象的類名,並使用Class.forName()。newInstance()創建工廠對象爲你。這可能是最簡單的方法。它爲您注入一個新的模擬工廠。

避免靜力學是一個好主意,但他們有自己的位置。如果您瞭解所涉及的權衡,請使用它們。

+0

謝謝Ian。我使用Spring注入工廠到構造函數中。對我來說,問題是如果我最終將方法轉換爲靜態,在這種情況下,我將使用Powermock來嘲弄靜態,或者保持原樣,並將我的Factory編碼爲接口 – Crowie

+0

我會說讓它編碼到一個接口。 Spring爲你做了繁重的工作,測試應該很簡單。我會說,如果你正在做DI,那麼使用靜態和新的消失的整個問題 - 這就是我要告訴你的老闆。 –

1

您不需要明確創建工廠。

將新實例的創建解壓縮到類中的受保護方法中,就像創建factory method一樣,但提供new ThriftColumnFamilyTemplate(...)作爲默認實現。

在你的單元測試中,你的sut將是類的部分模擬版本,嘲笑工廠方法,而不是真正的類。通過這種方法,未​​經測試的唯一代碼將是工廠方法,即單一一行。對於部分模擬,您可以使用EasyMock IMockBuilder