ios – Swift Singleton Init在XCTest中调用了两次

使用 Swift,在运行XCTest单元测试时会调用两次单例初始化程序.

但是,没有Objective-C的问题,init()方法只按预期调用一次.

以下是构建两个测试项目的方法

Objective-C的

单身人士班

使用测试创建一个空的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

AppDelegate中

在应用程序委托中添加对单例的调用,如下所示:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    [Singleton sharedInstance];
    return YES;
}

XCTestCase

还要对生成的测试类添加对单例的调用

- (void)testExample {
    [Singleton sharedInstance];
    // This is an example of a functional test case.
    XCTAssert(YES,@"Pass");
}

结果

如果向单例的init方法添加断点并运行测试,断点将只按预期命中一次.

迅速

现在创建一个新的Swift项目并做同样的事情.

独生子

创建单例,将测试目标添加到其目标成员资格

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)")
    }
}

AppDelegate中

func application(application: UIApplication,didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.
    Singleton.sharedInstance
    return true
}

XCTestCase

func testExample() {
    // This is an example of a functional test case.
    Singleton.sharedInstance
    XCTAssert(true,"Pass")
}

结果

这一次,如果你向单例的init方法添加断点并运行测试,断点将被击中两次,首先是来自app委托,然后来自测试用例,即你将有两个单例实例.

我错过了什么吗?

解决方法

由于应用程序模块和测试模块是分离的模块,因此当您将Singleton.swift文件添加到测试目标成员时,YourApp.Singleton和YourAppTest.Singleton不是同一个类.这就是为什么init叫了两次.

而不是那样,您应该在测试文件中导入主模块:

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.

相关文章

当我们远离最新的 iOS 16 更新版本时,我们听到了困扰 Apple...
欧版/美版 特别说一下,美版选错了 可能会永久丧失4G,不过只...
一般在接外包的时候, 通常第三方需要安装你的app进行测...
前言为了让更多的人永远记住12月13日,各大厂都在这一天将应...