iOS测试:dispatch_once被调用两次.首先在App中,在Test中排名第二.观察员的问题

Sam*_*Sam 10 testing observers grand-central-dispatch ios xctest

我有一个singelton类,它将在app delegate中创建.

当我运行XCTTests然后它再次创建它.

+ (instancetype)urlSchemeManager
{
    static dispatch_once_t onceToken;
    static UrlSchemeManager* _sharedInstance;

    dispatch_once(&onceToken, ^{

        _sharedInstance = [UrlSchemeManager new];


    });
    return _sharedInstance;
}
Run Code Online (Sandbox Code Playgroud)

这导致两个不同的实例.如果我只是用它进行单元测试,这没问题.但是在集成测试中,当我为urlSchmemeManager注册一个观察者时,我得到了一个EXC_BAD_ACCESS,因为它已经被rootViewController(在UI中)观察到了.

在RootViewController中:

UrlSchemeManager * schemeManager = [GlobalSpace globalSpace].urlSchemeManager;
[schemeManager addObserver:self forKeyPath:OBSERVER_KEY_URL_SCHEME_MANAGER_CONTENT_MORE options:NSKeyValueObservingOptionNew context:nil];
Run Code Online (Sandbox Code Playgroud)

有谁知道如何解决这个问题?

Mik*_*ini 30

我在运行测试套件时多次调用dispatch_once时遇到了同样的问题.我通过从测试的目标成员中删除单例类来修复它.

完成后,确保您的测试目标在"构建阶段"中依赖于您的应用程序,以便测试仍然知道该类.

之后,测试应该运行,单例只能实例化一次.


fsa*_*int 14

迈克的回答是对的!只需添加更多信息.这是一个非常棘手的问题.似乎应用程序目标和测试目标是分开编译的情况.但是,在运行时,测试的二进制文件将注入应用程序的空间.因为检测重复符号通常是编译器的工作,并且编译过程不同,所以可能会发生在运行时有两个类的实例.类的每个实例都有自己的静态变量集.这太超级怪了.大量奇怪的行为可以源于此.包括double dispatch_once_t执行.

我在cocoapods中遇到了这个问题.默认情况下,Podfile中的所有pod都链接到所有目标.因此,在运行XCTest时,您将在运行时具有重复的clases .解决方案是为每个目标指定您的pod.以我的情况为例.我做了:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '7.0'

target 'MyApp', :exclusive => true do
    pod 'AFNetworking'
    pod 'ObjectiveRecord', :head
    ...
end

target 'MyApp Tests', :exclusive => true do
  pod 'KIF', '~> 3.0', :configurations => ['Debug']
end

inhibit_all_warnings!
Run Code Online (Sandbox Code Playgroud)

我特别在ObjectiveRecord中遇到了单例模式的问题.因为核心数据上下文管理器类是两次创建的,所以我的应用程序的不同部分没有看到相同的数据.