2016-10-03 128 views
2

在我的應用程序中,我有一個封裝了Service的類,並具有返回資源和請求的方法。在我的測試中,我想嘲笑請求和資源的成功/失敗,而不進行任何實際的網絡調用。
由於Request是一個協議,很容易通過返回一個自定義的實現,只是調用onSuccessonFailure如何模擬資源響應?

但是要做到這一點,它不是返回一個Resource方法簡單,因爲Resource是最後類而不是協議。
我想創建一個模擬Resource,它在調用load()等時不會執行任何實際的網絡請求,並公開某種方式來僞造觸發觀察者添加到Resource的成功/失敗。

此刻有什麼辦法可以做到這一點?

回答

3

您有幾種選擇:

的Stub NetworkingProvider

與自定義NetworkingProvider實現創建您的服務。

// App 

var myAppNetworkingProvider: NetworkingProviderConvertible = 
    URLSessionConfiguration.ephemeral // Siesta default 
... 
Service(baseURL: "...", networking: myAppNetworkingProvider) 

// Tests 

myAppNetworkingProvider = NetworkStub() 

StubbedNetworkingProvider可以返回一個硬編碼的URLRequest ,或匹配,如果你想一次存根多個響應。

這是大多數應用程序的最佳選擇。你可以在Siesta’s own performance tests中看到它的一個例子。它簡單,快速,並提供細緻的控制,但仍然可以讓您用真實的Siesta行爲進行測試。

存根網絡

午睡可與像OHHTTPStubsMockingjayNocilla網絡磕碰庫。 (Siesta本身使用Nocilla進行自己的內部迴歸測試,雖然庫本身具有內部競爭條件,並且在撰寫本文時沒有特別好的維護,所以我不能全心全意地推薦它。)

對網絡本身進行存根擁有測試您的應用與底層網絡API的完整交互的優勢。這種方法對於全集成測試可能是最好的,特別是如果你想記錄和重放來自真實API的響應。

自定義資源協議

由於夫特支持retroactive modelingResource不需要是(或實施)一個可測試協議。你可以創建一個你自己的:

protocol ResourceProtocol { 
    // Resource methods your app uses 
} 

// No new methods; just adding conformance 
extension Resource: ResourceProtocol { } 

這聽起來最像你在你的原始問題中尋找什麼。不過,我並不特別推薦它:

  • 這是最複雜的實施 - 和最容易出錯。你會發現準確地模擬Siesta的所有行爲令人驚訝地很難。相信我:資源API起初似乎很清白,但如果您嘗試以這種方式來運用您的整個應用程序,您會發現自己重新實現了一半的庫。
  • 這很可能會漏掉問題,而不是迴歸。使用Siesta的許多危險地點必須處理確切的調用順序:哪些事件發生,以什麼順序發生,立即發生什麼,以及主循環的後續轉向,觀察者/所有者關係是做什麼或不做什麼創建保留週期等。您必須對所有這些事情做出假設,然後最終根據您的假設測試代碼 - 而不是違背圖書館的真實行爲。

總之,與其他方法相比,更低的價值努力。這當然不是進行迴歸測試的有效方法。這就是說,如果你堅持一個純粹主義者「不要超越界限」單元測試哲學,那麼這就是做這件事的方法。

1

我正在編寫一個使用Siesta的應用程序,我一直在使用URLMock來嘲笑Siesta製作的網絡請求。我對結果很滿意(它只是做了我想要的而沒有大驚小怪),但我相信其他庫也可以工作。我建議使用網絡模擬庫,它們具有您可能不會馬上想到的功能,例如設置爲在測試發出意外的網絡請求時返回錯誤。

下面是我設置URLMock與午睡工作:

override class func setUp() { 
    super.setUp() 
    UMKMockURLProtocol.enable() 
    UMKMockURLProtocol.setVerificationEnabled(true) 
} 

override class func tearDown() { 
    UMKMockURLProtocol.setVerificationEnabled(false) 
    UMKMockURLProtocol.disable() 
    super.tearDown() 
} 

override func setUp() { 
    super.setUp() 
    // Put setup code here. This method is called before the invocation of each test method in the class. 
    UMKMockURLProtocol.reset() 
    let testConfig = URLSessionConfiguration.ephemeral 
    testConfig.protocolClasses = [UMKMockURLProtocol.self] 
    service = Service(baseURL: expectedV2Host, useDefaultTransformers: true, networking: testConfig) 
}