Swift Singleton Init在XCTest中被称为两次 [英] Swift Singleton Init Called Twice in XCTest

查看:52
本文介绍了Swift Singleton Init在XCTest中被称为两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Swift中,运行XCTest单元测试时,单例初始化程序称为两次.

With Swift, a singleton initializer is called twice when running XCTest unit tests.

尽管Objective-C没问题,但是init()方法只被调用了一次,正如预期的那样.

No problems with Objective-C, though, the init() method is only called once, as expected.

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

Here's how to build the two test projects:

使用测试创建一个空的Objective-C项目.添加以下基本单身人士:

Create an empty Objective-C Project with tests. Add following bare-bones singleton:

#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

在应用程序委托中,像这样添加对单例的调用:

AppDelegate

In the application delegate add a call to the singleton like this:

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

XCTestCase

还将对单例的调用添加到生成的测试类:

XCTestCase

Also add a call to the singleton to the generated test class:

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

结果

如果将断点添加到单例的 init 方法中并运行测试,则断点只会被击中一次,如预期的那样.

Results

If you add a breakpoint to the singleton's init method and run the tests, the breakpoint will only be hit once, as expected.

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

Now do the create a new Swift project and do the same thing.

创建一个单例,将测试目标添加到其 Target Memberships

Create a singleton, add the test target to its 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)")
    }
}

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 方法中添加一个断点并运行测试,则该断点将被击中两次,首先是应用程序委托,然后是测试用例,即您将有两个单例实例.

Results

This time, if you add a breakpoint to the singleton's init method and run the tests, the breakpoint will be hit twice, first from the app delegate, then from the test case, i.e. you'll have two instances of the singleton.

我想念什么吗?

推荐答案

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

Since application module and tests module are separated modules, when you add the Singleton.swift file to test target member, YourApp.Singleton and YourAppTest.Singleton are not same class. That's why init called twice.

相反,您应该在测试文件中 import 主模块:

Instead of that, you should import your main module in your test file:

import YourAppName

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

和您的 Singleton 类必须声明为 public .参见 Swift,访问修饰符和单元测试

and your Singleton class must be declared as public. see 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 .

Don't forget to remove Singleton.swift from test target membership.

这篇关于Swift Singleton Init在XCTest中被称为两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆