Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIApplication.sharedApplication().delegate as AppDelegate causes EXC_BAD_ACCESS using it on swift unit test

I'm trying to use unit test in swift to test some of the real application behaviour. When i try to cast de UIApplicationDelegate to my AppDelegate from my test function i got and EXC_BAD_ACCESS exception. Below the test code:

func testGetAppDelegate(){

    let someDelegate = UIApplication.sharedApplication().delegate
    let appDelegate =  someDelegate as AppDelegate //EXC_BAD_ACCESS here
    XCTAssertNotNil(appDelegate, "failed to get cast pointer")
}

AppDelegate class is set to public so it is not a problem from access level.

Using objective-c in the same test target it works. Below the simple instruction:

AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];

The debuger says someDelegate is a Builtin.RawPointer. Don't know what that is, i am not familiar with low level details.

like image 809
MiguelSlv Avatar asked Nov 15 '14 14:11

MiguelSlv


2 Answers

I think you added AppDelegate.swift to the tests target members.

When you do that, AppName.AppDelegate and AppNameTests.AppDelegate becomes different classes. Then, UIApplication.sharedApplication().delegate returns AppName.AppDelegate instance, but you are trying to cast it to AppNameTests.AppDelegate type. That causes EXC_BAD_ACCESS.

Instead of that, you have to import it from your application module.

import UIKit
import XCTest
import AppName // <- HERE

class AppNameTests: XCTestCase {
   // tests, tests...
}

And, AppDelegate class and its methods and properties must be declared as public to be visible from test module.

import UIKit

@UIApplicationMain
public class AppDelegate: UIResponder, UIApplicationDelegate {

    public var window: UIWindow?

    public func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

    // ...

Again, Be sure to remove AppDelegate.swift from the Test target members.

like image 182
rintaro Avatar answered Nov 02 '22 03:11

rintaro


With the Swift 2.0 update, keep using rintaro's solution. But you can simplify it by:

@testable import MyApp

Then you don't need to mark your AppDelegate class as public.

like image 30
Dan M. Avatar answered Nov 02 '22 02:11

Dan M.