iOS Testing: dispatch_once get called twice. First in App, second in Test. Problems with Observers

一曲冷凌霜 提交于 2021-02-06 03:48:11

问题


I have a singelton class which will be create in the app delegate.

When i run XCTTests then its get create a second time.

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

    dispatch_once(&onceToken, ^{

        _sharedInstance = [UrlSchemeManager new];


    });
    return _sharedInstance;
}

This is resulting in two different instances. This was no problem if i just use it for unit test. But in the integration test, when i register an observer for urlSchmemeManager i get a EXC_BAD_ACCESS, because it was already observed by the rootViewController (in the UI).

In RootViewController:

UrlSchemeManager * schemeManager = [GlobalSpace globalSpace].urlSchemeManager;
[schemeManager addObserver:self forKeyPath:OBSERVER_KEY_URL_SCHEME_MANAGER_CONTENT_MORE options:NSKeyValueObservingOptionNew context:nil];

Does anyone has an idea how i can get around this problem?


回答1:


I had the same problem with dispatch_once being called multiple times when running a test suite. I fixed it by removing the singleton class from the Target Membership of the Test.

Once you've done that make sure that your test target is dependent on your application in "Build Phases" so that the test still knows about the class.

After that, the test should run and the singleton should only be instantiated one time.




回答2:


Mike's answer is correct! Just adding some more info. This is a really tricky issue. Seems to be the case that app target and the test target are compiled separated. In runtime, however, the binary for the tests is injected into the app's space. Because it is usually the compiler's job to detect duplicate symbols, and the compilation process is different, it can happen that you have two instances of a class at runtime. Each instance of the class with it's own set of static variables. This is super weird. Tons of weird behaviors can stem from this. Including the double dispatch_once_t execution.

I faced this problems in my cocoapods clases. All pods in your Podfile are, by default, linked into all targets. As a result you will have duplicate clases at runtime when running XCTest. The solution is to specify your pods per target. In my case, for example. I did:

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!

I specifically had issues with the singleton pattern in ObjectiveRecord. Because the core data context manager class was created twice, different sections of my app were not seeing the same data.



来源:https://stackoverflow.com/questions/21014843/ios-testing-dispatch-once-get-called-twice-first-in-app-second-in-test-probl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!