Skip to main content

Speed up your unit tests! Swap out your App Delegate for testing.

Faster, please
One thing that can slow our tests down is if our App performs expensive tasks on startup and it is not unusual to place code that synchronizes with a server in our implementation of UIAppDelegate.

Luckily for us there is a way to change the production App Delegate with a fake that does nothing.

Objective-C
class FakeAppDelegate: UIResponder, UIApplicationDelegate {
  var window: UIWindow?

  func application(application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
    self.window?.rootViewController = UIViewController()
    return true
  }
}

let isRunningTests = NSClassFromString("XCTestCase") != nil

if isRunningTests {
  UIApplicationMain(Process.argc, Process.unsafeArgv, nil,
    NSStringFromClass(FakeAppDelegate))
} else {
  UIApplicationMain(Process.argc, Process.unsafeArgv, nil,
    NSStringFromClass(AppDelegate))
}

Swift
class FakeAppDelegate: UIResponder, UIApplicationDelegate {
  var window: UIWindow?
  
  func application(_ application: UIApplication,
                   didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    self.window?.rootViewController = UIViewController()
    return true
  }
}

let isRunningTests = NSClassFromString("XCTestCase") != nil

// There is a Swift bug with the UIApplication signature in the newest Swift 3 version
// https://bugs.swift.org/browse/SR-1390
let unsafeArgv = UnsafeMutableRawPointer(CommandLine.unsafeArgv)
  .bindMemory(
    to: UnsafeMutablePointer.self,
    capacity: Int(CommandLine.argc))

if isRunningTests {
  UIApplicationMain(CommandLine.argc,
                    unsafeArgv,
                    nil,
                    NSStringFromClass(FakeAppDelegate.self)
  )
} else {
  UIApplicationMain(CommandLine.argc,
                    unsafeArgv,
                    nil,
                    NSStringFromClass(AppDelegate.self)
  )
}

Alex Salom

Comments