10

我有一个将在应用程序委托中创建的单点类。

当我运行 XCTTests 时,它会第二次创建。

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

    dispatch_once(&onceToken, ^{

        _sharedInstance = [UrlSchemeManager new];


    });
    return _sharedInstance;
}

这导致了两种不同的情况。如果我只是将它用于单元测试,这没问题。但是在集成测试中,当我为 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];

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

4

2 回答 2

33

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

完成此操作后,请确保您的测试目标依赖于“构建阶段”中的应用程序,以便测试仍然知道该类。

之后,测试应该运行并且单例应该只被实例化一次。

于 2014-01-30T22:51:55.603 回答
14

迈克的答案是正确的!只是添加更多信息。这是一个非常棘手的问题。似乎是 app 目标和测试目标是分开编译的。然而,在运行时,测试的二进制文件被注入到应用程序的空间中。因为检测重复符号通常是编译器的工作,并且编译过程不同,所以在运行时可能会出现一个类的两个实例。类的每个实例都有自己的一组静态变量。这太奇怪了。大量奇怪的行为可能源于此。包括双重dispatch_once_t执行。

我在我的cocoapods类中遇到了这个问题。默认情况下, Podfile中的所有pod都链接到所有目标。因此,在运行XCTest时,您将在运行时出现重复的类。解决方案是为每个目标指定您的 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!

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

于 2014-12-05T16:47:05.617 回答