2014-10-10 60 views
1

我努力學習各種測試與快速,靈活的和我寫了簡單的單身主義者和一些測試斯威夫特單測試

辛格爾頓:

public class LocationManager : NSObject { 
// Singleton 
public class var sharedInstance : LocationManager { 
    struct Static { 
     static var instance : LocationManager? 
     static var token : dispatch_once_t = 0 
     } 
    dispatch_once(&Static.token) { 
     Static.instance = LocationManager() 
    } 
    return Static.instance! 
    } 
} 

我的測試:

class LocationManagerSpec: QuickSpec { 
override func spec() { 
    describe("Location manager") { 

     let locationManager = LocationManager.sharedInstance 

     context("initialized") { 
      it("is not nil") { 
       expect(locationManager).notTo(beNil()) 
      } 
      it("is unique") { 
       let tempLocationManager = LocationManager() 
       expect(locationManager).notTo(equal(tempLocationManager)) 
      } 
      it("and shared instances are same") { 
       let tempLocationManager = LocationManager.sharedInstance 
       expect(locationManager).to(equal(tempLocationManager)) 
      } 
     } 
    } 
} 
} 

我怎樣才能測試我的單例是線程安全的?

回答

0

爲了測試你的單例是線程安全的,我做了一個小示例。您可以在此Github repo基本上所有代碼:

  1. 創造了一堆線程,要求單身
  2. 每次返回的對象存儲陣列
  3. 檢查包含在陣列中的所有對象中都是一樣的

我發現了幾個問題(使用Xcode 6.2 ergo Swift 1.1),甚至編譯器崩潰。所以在this accepted SO answer之後,我改變了你的Singleton實現,避免了經典的GCD使用。這些指針和不安全可變的指針,你需要管理,而我得到的,因爲這

崩潰所以你的Singleton類現在是:

import Foundation 


public class LocationManager: NSObject { 

    public class var sharedInstance: LocationManager { 
     struct Static { 
      static let instance: LocationManager = LocationManager() 
     } 
     return Static.instance 
    } 

} 

,並測試它,你需要等到所有線程都完了。由於測試運行的MainThread運行,你需要使用一個期望

describe("Accesing Location manager from multiple concurrent threads") { 
      context("When created") { 
       it("should return always the same object for every of these 500 threads") { 
        var allSingletons = Array<LocationManager>() 

        for i in 1...10 { 
         println("Launching thread \(i)") 

         dispatch_async(self.globalBackgroundQueue) { 
          allSingletons.append(LocationManager.sharedInstance) 
         } 
        } 

        expect(self.allSingletonsEqual(inArray: allSingletons, singleton: LocationManager.sharedInstance)).toEventually(beTrue(), timeout: 10) 

       } 
      } 

     } 

最重要的部分是這個:

expect(self.allSingletonsEqual(inArray: allSingletons, singleton: LocationManager.sharedInstance)).toEventually(beTrue(), timeout: 10) 

這裏我打電話的功能,以確保如果每一個存儲的對象是一樣的通過辛格爾頓,並給予10秒後超時

整個測試類:

import Quick 
import Nimble 
import QuickNimbleExample 




class LocationManagerSpec: QuickSpec { 
    var globalBackgroundQueue: dispatch_queue_t { 
     return dispatch_get_global_queue(Int(QOS_CLASS_BACKGROUND.value), 0) 
    } 

    func allSingletonsEqual(#inArray: Array<LocationManager>, singleton: LocationManager) -> Bool { 

     for loc in inArray { 
      if loc != singleton { 
       return false 
      } 
     } 

     return true 
    } 


    override func spec() { 

     describe("Accesing Location manager from multiple concurrent threads") { 
      context("When created") { 
       it("should return always the same object for every of these 500 threads") { 
        var allSingletons = Array<LocationManager>() 

        for i in 1...10 { 
         println("Launching thread \(i)") 

         dispatch_async(self.globalBackgroundQueue) { 
          allSingletons.append(LocationManager.sharedInstance) 
         } 
        } 

        expect(self.allSingletonsEqual(inArray: allSingletons, singleton: LocationManager.sharedInstance)).toEventually(beTrue(), timeout: 10) 

       } 
      } 

     } 


      } 
}