2014-10-10 59 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) 

       } 
      } 

     } 


      } 
}