如何讓系統單例更易測試

2021-09-11 14:10:16 字數 1718 閱讀 7726

下面是乙個使用 urlsession.share 單例的常見網路任務**:

enum

serviceresult

class

dataloaderservice

completionhandler(.success(data ?? data()))

}task.resume()

}}複製**

urlsession.shared 單例讓我們在測試時不得不面對等待和超時的情況,隨著使用的地方增多**的測試性更是會直線下降。

為了讓**對測試更為友好,我們可以使用 mock 方式將上訴**中的單例替換掉。而要實現該目標,第一步我們就需要將上訴函式中的功能抽象為協議中的介面。

protocol

networkengine

複製**

介面宣告好之後接下來就是讓 urlsession 實現該協議:

extension

urlsession: networkengine

}複製**

這樣後面我們 mock 的時候只需要關注 networkengine 就好。

為了保證原有 load 中的處理不變,接下來我們需要將 urlsession.shared 單例作為依賴注入 dataloaderservice 。

class

dataloaderservice

func

load

(from url: url, completionhandler: @escaping (result)

-> void)

completionhandler(.success(data ?? data()))}}

}複製**

這裡通過預設引數的方式,我們將原有的 urlsession.share 單例作為依賴注入到 dataloaderservice 中保證了原有功能的不變。

在上面的改造完成後,我們就可以在進行單元測試時使用 mock 的方式解決單例在測試中的問題。

func

testloadingdata()

}let engine = networkenginemock()

let loader = dataloaderservice(engine: engine)

var result: serviceresult?

let url = url(string: 「mock/api」)!

loader.load(from: url)

xctassertequal(engine.requestedurl, url)

xctassertequal(result, .data(「hello world」.data(using: .utf8)!))

}複製**

在上訴**中我實現了乙個 networkengine 協議的簡單 mock 類,並且將其作為依賴性注入到 dataloaderservice 例項中。在 mock 類 networkenginemock 我們並沒有真正的請求網路介面而是直接返回硬編碼,這樣進一步減少了測試時的複雜度。

通過上面三個簡單的步驟,我們就能完成讓原有的方法變得更易測試。當然該方法並不囿於系統單例的使用場景的改造,這種面向協議的介面服務設計在 swift 中有更大的舞台。

原文位址

單例模式 單例類 Singleton 內含測試類

單例類 singleton public class singleton public void setname string name 1.餓漢式 建立乙個靜態私有物件 private final static singleton instance new singleton 私有化構造方法 pr...

作業系統 單例程序 單例守護程序

一 單例程序 檔案鎖主函式 二 單例守護程序 filelock.h ifndef filelock h define filelock h include include include include include include include include fcntl函式的包裝,帶w表示阻...

軟體測試用例檢查單

1.是否涵蓋了 需求文件上的每個功能點 2.是否涵蓋了需求文件上的每條業務規則說明 3.是否覆蓋了輸入條件的各種有意義組合 4.是否覆蓋了業務操作的基本路徑和異常路徑 5.是否考慮了重要表單字段的資料合法性檢查 6.是否考慮了其他的測試型別 對某個功能很重要,但未在需求文件中提及的,如安全測試 週期...