使用Swift时,单个初始化程序在运行XCTest单元测试时称为两次。
没有Objective-C的问题,init()方法只按预期调用一次。
以下是如何构建两个测试项目:
使用测试创建一个空的Objective-C项目。添加以下裸机单例:
#import "Singleton.h"
@implementation Singleton
+ (Singleton *)sharedInstance
{
static Singleton *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[Singleton alloc] init];
// Do any other initialisation stuff here
});
return sharedInstance;
}
- (instancetype)init
{
self = [super init];
if (self) {
NSLog(@"%@", self);
}
return self;
}
@end
在应用程序委托中添加对单例的调用,如下所示:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[Singleton sharedInstance];
return YES;
}
还要对生成的测试类添加对单例的调用:
- (void)testExample {
[Singleton sharedInstance];
// This is an example of a functional test case.
XCTAssert(YES, @"Pass");
}
如果向单例的init
方法添加断点并运行测试,断点将只按一次,如预期的那样。
现在创建一个新的Swift项目并做同样的事情。
创建单例,将测试目标添加到其Target Memberships
class Singleton {
class var sharedInstance : Singleton {
struct Static {
static var onceToken : dispatch_once_t = 0
static var instance : Singleton? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = Singleton()
}
return Static.instance!
}
init() {
NSLog("\(self)")
}
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
Singleton.sharedInstance
return true
}
func testExample() {
// This is an example of a functional test case.
Singleton.sharedInstance
XCTAssert(true, "Pass")
}
这一次,如果你向单例的init
方法添加一个断点并运行测试,那么断点将首先从app委托中被击中两次,,然后从测试用例中,即你将有两个单身实例。
我错过了什么吗?
答案 0 :(得分:8)
由于应用程序模块和测试模块是分离的模块,因此当您将Singleton.swift
文件添加到测试目标成员时,YourApp.Singleton
和YourAppTest.Singleton
不是同一类。这就是init
两次调用的原因。
而不是那样,您应该在测试文件中import
主模块:
import YourAppName
func testExample() {
// This is an example of a functional test case.
Singleton.sharedInstance
XCTAssert(true, "Pass")
}
并且您的Singleton
类必须声明为public
。见Swift, access modifiers and unit testing
public class Singleton {
public class var sharedInstance : Singleton {
struct Static {
static var onceToken : dispatch_once_t = 0
static var instance : Singleton? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = Singleton()
}
return Static.instance!
}
init() {
NSLog("\(self)")
}
}
不要忘记从测试目标成员资格中删除Singleton.swift
。