[英]Does the self-shunt testing pattern violate the Single Responsibility Principle?
這些年來,我已經多次使用自分流單元測試模式。 正如我最近向某人解釋的那樣,他們爭辯說它違反了 SRP。 論點是,現在可以出於以下兩個原因之一更改測試類:當測試更改時,或者當測試正在實現的接口上的方法簽名更改時。 想了想,好像這個評價是正確的,但是想聽聽別人的意見。 想法?
參考:http ://www.objectmentor.com/resources/articles/SelfShunPtrn.pdf
我對此的看法是,測試類在技術上違反了 SRP,但並未違反 SRP 的精神。 自分流的替代方法是將模擬類與測試類分開。
對於單獨的模擬類,您可能認為它是完全自包含的並且滿足 SRP,但是與模擬類屬性的語義耦合仍然存在。 所以,真的,我們沒有實現任何有意義的分離。
以PDF為例:
public class ScannerTest extends TestCase implements Display
{
public ScannerTest (String name) {
super (name);
}
public void testScan () {
// pass self as a display
Scanner scanner = new Scanner (this);
// scan calls displayItem on its display
scanner.scan ();
assertEquals (new Item (“Cornflakes”), lastItem);
}
// impl. of Display.displayItem ()
void displayItem (Item item) {
lastItem = item;
}
private Item lastItem;
}
現在我們做一個模擬:
public class DisplayMock implements Display
{
// impl. of Display.displayItem ()
void displayItem (Item item) {
lastItem = item;
}
public Item getItem() {
return lastItem;
}
private Item lastItem;
}
public class ScannerTest extends TestCase
{
public ScannerTest (String name) {
super (name);
}
public void testScan () {
// pass self as a display
DisplayMock dispMock = new DisplayMock();
Scanner scanner = new Scanner (dispMock );
// scan calls displayItem on its display
scanner.scan ();
assertEquals (new Item (“Cornflakes”), dispMock.GetItem());
}
}
實際上(恕我直言), TestClass
與DisplayMock
的更高耦合比違反TestClass
的 SRP 更有害。 此外,使用模擬框架,這個問題就完全消失了。
編輯我剛剛在 Robert C. Martin 的優秀著作Agile Principles, Patterns, and Practices in C# 中簡單提到了自分流模式。 這是書中的片段:
我們可以通過使用數據庫的抽象接口來實現這一點。 此抽象接口的一種實現使用真實數據庫。 另一種實現是編寫測試代碼來模擬數據庫的行為並檢查數據庫調用是否正確。 圖 29-5 顯示了該結構。
PayrollTest
模塊通過調用它來測試PayrollModule
並實現Database
接口,以便它可以捕獲Payroll
對數據庫的調用。 這允許PayrollTest
確保Payroll
正常運行。 它還允許PayrollTest
模擬多種數據庫故障和其他難以創建的問題。 這是一種稱為 SELF-SHUNT 的測試模式,有時也稱為mocking或spoofing 。
因此,創造 SRP(在同一本書中有詳細討論)的人對使用自分流模式毫不猶豫。 鑒於此,我會說在使用此模式時,您可以避免 OOP(面向對象的警察)。
在我看來,這是一種違規行為,但非常輕微。
您的測試類現在是一個測試類,並且是您正在測試的任何內容的依賴項。
然而,這是一件壞事嗎? 對於幾個簡單的測試,可能不是。 隨着測試用例數量的增加,您可能想要重構並使用模擬類來分離一些關注點。 (正如您粘貼的鏈接所說,自我分流是嘲笑的墊腳石)。 但是,如果測試用例的數量保持不變且很少,那有什么問題呢?
我認為需要一點實用主義。 它是否違反了 SRP? 是的,但我猜可能沒有您正在測試的系統中的某些代碼那么多。 你需要做些什么嗎? 不,只要代碼清晰且可維護,這對我來說始終是底線。 SRP 是指導方針,而不是規則。
如果正在實現或分流的接口發生變化,則測試套件很可能也必須發生變化。 所以我真的不認為這是對 SRP 的違反。
我更喜歡對我正在創建的模擬/存根有更多的控制。 當我嘗試使用自分流模式時,我最終使我的測試類更加復雜。 通過在測試方法中將模擬創建為局部變量,我最終得到了更簡潔的代碼。
FWIW 除非您使用像 C#(或 python 或等效的)這樣強大的東西,否則當您更改接口時,您的測試代碼將會更改。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.