[英]Is creating a private constructor for testing bad practice?
我遇到了一些java代碼,其中公共構造函數調用一個包私有構造函數,其中包含一堆new
運算符來創建新對象。
public class Thing {
//public
public Thing(String param1, int paramm2) {
this(param1, param2, new Dependency1(), new Dependency2());
}
//package-private for the sake of testing
Thing(String param1, int param2, Dependency1 param3, Dependency2 param4) {
this.memberVar1 = param1;
this.memberVar2 = param2;
this.memberVar3 = param3;
this.memberVar4 = param4;
}
//...rest of class...
}
在我看來,這是錯誤的,因為您正在編寫代碼來測試它而不是編寫正確的代碼。 我想其他兩個選項(我能想到的)是創建工廠或使用PowerMockito
在適用的情況下注入新對象。 就個人而言,我會寫如下所示。
public class Thing {
//public
public Thing(String param1, int paramm2) {
this.memberVar1 = param1;
this.memberVar2 = param2;
this.memberVar3 = new Dependency1();
this.memberVar4 = new Dependency2();
}
//...rest of class...
}
實施此方法的最佳做法/正確方法是什么?
在任何已發布的內容中包含特定於測試的代碼通常是不好的形式(但有例外情況,所以不要過於仔細地閱讀)。 這有幾個原因。
1.外部人員可能會以一種你從未想過的方式使用測試構造函數,因為他們要么沒有讀取指示它用於測試的文檔,要么開發人員忘記記錄它。
假設您想要寫一些有用的Thing
擴展,但是您在Thing
的公共/受保護API中找不到任何您想要的東西。 然后你會發現這個包私有構造函數似乎允許你想要的東西,但后來才發現它破壞了你的代碼。 你仍然無法做你想做的事情,你浪費時間探索沒有成功的部分API。 任何執行此操作的人都將對API持否定意見,並且不太可能將其推薦給其他任何人。
2.重構包名稱會破壞內容。
由於Java默認可見性的工作方式,此測試代碼對生產代碼中發生的重構不具有很強的適應性。 如果測試代碼位於同一個包中,則它只能調用該構造函數。 如果重命名包,則調用它的測試代碼將無法訪問它,從而導致編譯錯誤。 當然,對於開發代碼和測試的人來說,這是一個簡單的解決方案,但即使沒有添加這個小麻煩,重構也已經不好玩了。 如果一群人以前能夠成功地使用包私有的東西來滿足他們的需求,那么它就成了一個主要問題 - 現在他們所有的代碼都被打破了。
在某些情況下,很難編寫可以在測試和生產環境中運行的代碼(例如,僅在應用程序聯網時運行的功能)。 在這些情況下,依賴注入可能是你的朋友,但更簡單的測試總是最好的,如果可以避免更復雜的測試方案而不犧牲功能覆蓋或在API中添加鈎子,你從未打算讓其他開發人員看到。
我知道在StackExchange的其他地方對這個確切的話題進行了很好的討論,但我現在對谷歌的好運並不強烈。 我發現的副本不太有啟發性。
就個人而言,我已經在生產中看到了三種類型的測試代碼。
if (isTesting) foo() else bar();
Object foo();
通過測試代碼調用但從未在生產中調用。 Foo(Object dependency1, Object dependency2)
通過測試代碼調用,但從未在生產中調用。 前兩種類型在幾個方面都是有害的。
第三種類型當然可以以上面列出的相同方式有害; 但是,我相信所謂的測試構造函數可以減輕或消除生產中其他類型測試代碼固有的問題。
在構造函數內部調用new
通常是不好的,因為依賴注入通常是好的。 但是,在某些情況下,類的依賴項的合理默認實現是顯而易見的,並且在構造函數中實例化這些依賴項為客戶端提供了最簡單的可能接口。 在這些場景中,我發現鏈接第二個構造函數是合適的,它不會強制任何默認值,無論第二個構造函數是否有助於測試。
作為獎勵,鏈式構造函數實踐鼓勵編程到接口,因為第二個構造函數使您考慮除默認值之外的依賴項實現。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.