2016-08-24 52 views
1

我有一个OS X应用程序,它在启动时从服务器加载一些数据并将通知推送到NSUserNotificationCenter。 现在我有这个问题,这也发生在我的单元测试。我发现还没有办法阻止这一点。当然,我可以存根HTTP负载。但在某些情况下,我想测试加载,然后发送通知。Swift:如何在测试期间不加载AppDelegate

我想要做的是使测试运行不加载AppDelegate但我只用于测试的假的。我在UIApplicationMain上找到了几个关于如何做到这一点的例子[1],在这里你可以传递一个特定的AppDelegate类名。 NSApplicationMain [2]也是不可能的。

我已经试过如下:

AppDelegate.swift删除@NSApplicationMain,然后添加一个main.swift具有以下内容:

class FakeAppDelegate: NSObject, NSApplicationDelegate { 
} 

NSApplication.sharedApplication() 
NSApp.delegate = FakeAppDelegate() 
NSApplicationMain(Process.argc, Process.unsafeArgv) 

此代码测试之前运行,但没有任何效果可言。我可能不得不说:我的AppDelegate几乎是空的。为了处理MainMenu.xib的东西,我做了一个单独的视图控制器,它在awakeFromNib中执行实际的加载和通知。

[1] http://www.mokacoding.com/blog/prevent-unit-tests-from-loading-app-delegate-in-swift/

[2] https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Miscellaneous/AppKit_Functions/#//apple_ref/c/func/NSApplicationMain

回答

1

后的尝试和失败我天发现了Apple forums答案:

的问题是,我main.swift文件是在NSApplication初始化之前初始化我的AppDelegate。 Apple文档清楚地表明,很多其他Cocoa类都依赖NSApplication在初始化时启动并运行。显然,NSObject和NSWindow是其中两个。

所以main.swift我最后和工作的代码如下所示:

private func isTestRun() -> Bool { 
    return NSClassFromString("XCTest") != nil 
} 

private func runApplication(
    application: NSApplication = NSApplication.sharedApplication(), 
    delegate: NSObject.Type? = nil, 
    bundle: NSBundle?   = nil, 
    nibName: String   = "MainMenu") { 

    var topLevelObjects: NSArray? 

    // Actual initialization of the delegate is deferred until here: 
    application.delegate = delegate?.init() as? NSApplicationDelegate 

    guard bundle != nil else { 
     application.run() 
     return 
    } 

    if bundle!.loadNibNamed(nibName, owner: application, topLevelObjects: &topLevelObjects) { 
     application.run() 
    } else { 
     print("An error was encountered while starting the application.") 
    } 
} 

if isTestRun() { 
    let mockDelegateClass = NSClassFromString("MockAppDelegate") as? NSObject.Type 
    runApplication(delegate: mockDelegateClass) 
} else { 
    runApplication(delegate: AppDelegate.self, bundle: NSBundle.mainBundle()) 
} 

所以实际的问题之前,是在测试过程中被加载的笔尖。这个解决方案阻止了这一点只要它检测到测试运行,它就会使用模拟的应用程序委托加载应用程序(通过查找XCTest类)。我相信我将不得不调整这一点。特别是当用户界面测试开始时。但目前它的工作。