2016-05-03 45 views
2

我有一個Swift類,我正在進行單元測試。該類的主要目的是進行HTTP調用。我剛剛使用Mockingjay完成了嘲笑所有網絡請求,但我想確保今後不會忘記嘲笑未來的請求。雖然我在做最初的嘲弄,但是我用一個不起作用的基礎URL替換了,但我想保留,僅限於我的測試。被測類看起來是這樣的:如何重寫一個Swift類屬性進行測試

public class MyWebServiceWrapper { 
    ... 

    public class var baseURL: String { 
     return "https://api.thesite.com" 
    } 

    ... 
} 

我試圖使用OCMock從Objective-C類來代替baseURL的實現,我已經使用方法混寫as described on NSHipster以及嘗試(我使類從NSObject派生,並用一種​​方法代替baseURL而不是上面顯示的屬性 - 我寧可不要調整,尤其是因爲我不需要這個類是一個NSObject子類)。

這是我用來執行企圖swizzle,沒有任何效果的代碼。對於這兩種嘗試以下解決方案,我改寫了我的測試類,像這樣(因爲它看起來像沒有辦法將與雨燕性質或純雨燕類工作得很好):

​​3210

這是我混寫的嘗試(斯威夫特) 。根據日誌,我每次都會點擊else聲明,以便它能幫助找出發生的事情。

extension MyWebServiceWrapper { 

    public override class func initialize() { 
     struct Static { 
      static var token: dispatch_once_t = 0 
     } 

     if self !== MyWebServiceWrapper.self { 
      return 
     } 

     dispatch_once(&Static.token) { 
      NSLog("Replacing MyWebServiceWrapper base URL...") 
      let originalSelector = #selector(baseURLValue) 
      let swizzledSelector = #selector(networkFreeBaseURL) 

      guard let klass = object_getClass(self) else { 
       return 
      } 

      let originalMethod = class_getClassMethod(klass, originalSelector) 
      let swizzledMethod = class_getClassMethod(klass, swizzledSelector) 

      let didAddMethod = class_addMethod(klass, originalSelector, 
               method_getImplementation(swizzledMethod), 
               method_getTypeEncoding(swizzledMethod)) 

      if didAddMethod { 
       NSLog("MyWebServiceWrapper method added") 
       class_replaceMethod(klass, swizzledSelector, method_getImplementation(originalMethod), 
            method_getTypeEncoding(originalMethod)) 
      } else { 
       method_exchangeImplementations(originalMethod, swizzledMethod) 
       NSLog("MyWebServiceWrapper implementation replaced") 
      } 
     } 
    } 

    class func networkFreeBaseURL() -> String { 
     return "https://tests-shouldnt-hit-the-network.com" 
    } 

} 

這就是我試圖用OCMock替換方法(在Objective-C中)。代碼在配置我的單元測試期間被調用。

id wrapperMock = OCMClassMock([MyWebServiceWrapper class]); 
OCMStub(ClassMethod([wrapperMock baseURLValue])).andReturn(@"https://tests-shouldnt-hit-the-network.com"); 

什麼是實現我返回從baseURL無效值的目標,正確的方法是什麼?

+0

你需要找到另一種方式,因爲否則它是一個解決辦法:( 你找到任何解決方案 – denis631

+1

@ denis631我還是?使用我在下面提供的答案 – Dov

+0

傷心......這似乎不正確,但你知道...... GTD:取得東西完成:) – denis631

回答

1

我對它並不完全滿意(換句話說,我仍然喜歡其他答案),因爲它需要對被測試的類的代碼進行修改,但這是我最終的結果。它完成了工作,並且不容易被非測試代碼濫用,因爲我使覆蓋變量爲internal

public class MyWebServiceWrapper { 
    ... 

    /// Only use for testing! 
    internal static var baseURLOverride: String? 

    public class var baseURL: String { 
     return baseURLOverride ?? "https://api.thesite.com" 
    } 

    ... 
} 

而且從我的測試配置中:

@testable 
import MyFramework 

... 

// Inside test configuration 
MyWebServiceWrapper.baseURLOverride = "https://tests-shouldnt-hit-the-network.com"