I have an OS X application which on startup loads some data from a server and pushes notifications to the NSUserNotificationCenter
.
Now I have the problem that this also happens during my unit tests. I found no way yet to prevent this. Of course I could stub the HTTP loads. But in some cases I want to test the loading and then the notifications get sent anyway.
What I'm trying to do is to make the test runs not load the AppDelegate
but a fake one that I'm only using for tests. I found several examples [1] on how to do that with UIApplicationMain
, where you can pass a specific AppDelegate class name. The same is not possible with NSApplicationMain
[2].
What I've tried is the following:
Removed @NSApplicationMain
from AppDelegate.swift
, then added a main.swift
with the following content:
class FakeAppDelegate: NSObject, NSApplicationDelegate {
}
NSApplication.sharedApplication()
NSApp.delegate = FakeAppDelegate()
NSApplicationMain(Process.argc, Process.unsafeArgv)
This code runs before tests but has no effect at all.
I might have to say: My AppDelegate is almost empty. To handle the MainMenu.xib stuff I made a separate view controller which does the actual loading and notification stuff in 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
AppDelegate is responsible for handling application-level events, like app launch and the SceneDelegate is responsible for scene lifecycle events like scene creation, destruction and state restoration of a UISceneSession.
UIApplicationMain first instantiates UIApplication and retains its instance to serve as the shared application instance ( UIApplication. shared ) and then instantiates the app delegate marked @Main as the application instance's delegate. The main method exists as a type method.
The app delegate is effectively the root object of your app, and it works in conjunction with UIApplication to manage some interactions with the system. Like the UIApplication object, UIKit creates your app delegate object early in your app's launch cycle so it's always present.
Use the XCTest framework to write unit tests for your Xcode projects that integrate seamlessly with Xcode's testing workflow. Tests assert that certain conditions are satisfied during code execution, and record test failures (with optional messages) if those conditions aren't satisfied.
Just an update on the previous accept answer, this is my main.swift
:
private func isTestRun() -> Bool {
return NSClassFromString("XCTestCase") != nil
}
if isTestRun() {
// This skips setting up the app delegate
NSApplication.shared.run()
} else {
// For some magical reason, the AppDelegate is setup when
// initialized this way
_ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)
}
A bit more compact! I'm using Swift 4.1 and XCode 9.4.1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With