重構由許多小的技術性步驟組成。這些步驟統稱為 技巧。如果您象按照食譜那樣嚴格遵循這些技術, 那么您在學習重構時應該沒有太大的麻煩。
- 標識創建或獲取合作者的代碼的所有出現。
- 將
抽取方法重構應用于這個創建代碼,創建工廠方法(在 Fowler 書籍的第 110 頁中討論;有關更多信息,請參閱
參考資料一節)。
- 確保目標對象及其子類可以訪問工廠方法。(在 Java 語言中,使用
protected
關鍵字)。
- 在測試代碼中,創建模仿對象且實現與合作者相同的接口。
- 在測試代碼中,創建擴展(專用于)目標對象的特殊化對象。
- 在特殊化對象中,覆蓋創建方法以返回為測試提供的模仿對象。
- 可選的:創建單元測試以確保原始目標對象的工廠方法仍返回正確的非模仿對象。
設想您正在編寫用于銀行自動柜員機(Automatic Teller Machine)的測試。其中一個測試可能類似于清單 2:
清單 2. 初始單元測試,在模仿對象引入之前
public void testCheckingWithdrawal() { |
另外,
AtmGui
類內部的匹配代碼可能類似于清單 3:
清單 3. 產品代碼,在重構之前
private Status doWithdrawal(Account account, float amount) { |
該方法將起作用,遺憾的是,它有一個副作用:支票帳戶余額比測試開始時少,這使得其它測試變得更困難。 有一些解決這種困難的方法,但它們都會增加測試的復雜性。 更糟的是,該方法還需要對管理貨幣的系統進行三次往返。
要修正這個問題,第一步是重構
AtmGui
以允許我們用模仿事務替換實際事務,
如清單 4 中所示(比較
粗體的源代碼以查看我們正在更改什么):
清單 4. 重構 AtmGui
private Status doWithdrawal(Account account, float amount) { |
后退到測試類內部,我們將
MockTransaction
類定義為成員類,如清單 5 中所示:
清單 5. 將 MockTransaction 定義為成員類
private MockTransaction extends Transaction { |
最后,我們可以重寫測試,以便被測試的對象使用
MockTransaction
類,而不是使用實際類,如清單 6 中所示:
文章來源于領測軟件測試網 http://www.kjueaiud.com/