小酌重構系列 9 分解依賴

2021-09-08 04:07:17 字數 2323 閱讀 6047

編寫單元測試有助於改善**的質量,在編寫單元測試時,某些功能可能依賴了其他**(比如呼叫了其他元件)。

通常我們只想測試這些功能本身,而不想測試它所依賴的**。

為什麼呢?

單元測試的目標是驗證該功能是否正確,然而功能所依賴的**是處於功能範圍外的,這些**可能是一些外部的元件,單元測試無法驗證這些外部元件的準確性。

單元測試因呼叫「依賴的**」出錯而失敗時,會影響測試結果的判斷,我們無法確定功能本身是否是正確的。

也許功能是正確的,但呼叫依賴的**出錯時,這個單元測試仍然會被認為是失敗的。

如果要測試這些被依賴的**,我們應該另外地為這些**編寫單元測試。

如何解決?

「依賴的**」成了我們編寫這類單元測試的攔路石,我們可以通過2種方式來解決這個問題:

1. mock依賴的**

2. 分解依賴

mock的強大是毋庸置疑的,然而mock不是萬能的,它也是有限制的,我們不能在單元測試中mock靜態類。

但是,通過「分解依賴」可以解決這個問題,本文將通過乙個示例來演示這2種方式。

這段**描述了乙個場景——「飼養動物」,它包含2個類:

animalfeedingservice(動物飼養服務),以及靜態類feeder(飼養員)。

animalfeedingservice描述了「飼養」行為,feeder類描述了「補充食物」行為。

在飼養動物時,如果動物的食盆是空的,則飼養員需要補充食物。

/// /// 動物飼養服務

///

public class animalfeedingservice

public void feed()

}/// /// 飼養員

///

public static class feeder

}

單元測試**(基於xunit和rhino.mocks框架)

public class animalfeedingservicetests

}

由於feeder是乙個靜態類,所以在為animalfeedingservice編寫單元測試時,我們無法mock feeder類,而且feeder類的功能我們也不想在這個單元測試中驗證。

如果在呼叫feeder.replenishfood()時就出錯了,這個單元測試的執行就是失敗的。

同時,feed()方法的正確性也無法驗證。

為了能在單元測試中解除對feeder類的依賴,我們可以為feeder類新增包裝介面ifeederservice,然後讓animalfeedingservice依賴於這個包裝介面。這樣在animalfeedingservicetest類中,我們就不需要考慮feeder類了。

/// /// 動物飼養服務

///

public class animalfeedingservice

public ifeederservice feederservice

public animalfeedingservice(ifeederservice feederservice)

public void feed()

}/// /// 飼養服務介面

///

public inte***ce ifeederservice

/// /// 飼養服務實現

///

public class feederservice : ifeederservice

}/// /// 飼養員

///

public static class feeder

}

單元測試**(基於xunit和rhino.mocks框架)

public class animalfeedingservicetests

}

重構後的animalfeedingservicetests,由於ifeederservice是mock的,所以ifeederservice的replenishfood()方法根本不會被呼叫,因此feeder的replenishfood()方法也不會被呼叫。

呼叫feed()方法時,feeder.replenishfood()方法被忽略了,這可以讓我們更加關注於feed()方法本身的邏輯。

小酌重構系列目錄彙總

關注keepfool

小酌重構系列 12 去除上帝類

神說 要有光 就有了光。聖經 上帝要是會寫程式,他寫的類一定是 上帝類 程式設計師不是上帝,不要妄想成為上帝,但程式設計師可以寫出 上帝類 上帝是唯一的,上帝的光芒照耀人間,上帝是很愛面子的,他知道程式設計師寫了 上帝類 搶了他的風頭,於是他降下神罰要懲戒程式設計師。既然你寫了 上帝類 那麼就將你流...

小酌重構系列 17 提取工廠類

在程式中建立物件,並設定物件的屬性,是我們長幹的事兒。當建立物件需要大量的重複 時,看起來就不那麼優雅了。從類的職責角度出發,業務類既要實現一定的邏輯,還要負責物件的建立,業務類幹的事兒也忒多了點。物件建立也是 一件事 我們可以將 這件事 從業務 中提取出來,讓專門的類去做 這件事 這個專門的類一般...

小酌重構系列 21 避免雙重否定

在自然語言中,雙重否定表示肯定。但是在程式中,雙重否定會降低 的可讀性,使程式不易理解,容易產生錯覺。人通常是用 正向思維 去理解一件事情的,使用雙重否定的判斷,需要開發者以 逆向思維 的方式去理解它的含義。另外,在寫程式時,符號很容易被疏忽和遺漏,一不小心則會編寫出錯誤的 從而產生bug。所以,在...