UIApplication.sharedApplication().делегат как AppDelegate вызывает EXC плохой доступ, используя его в модульном тесте swift

Я пытаюсь использовать модульный тест в swift, чтобы проверить некоторые из реального поведения приложения. Когда я пытаюсь бросить de UIApplicationDelegate мой AppDelegate из моей тестовой функции я получил исключение EXC_BAD_ACCESS. Под кодом теста:

func testGetAppDelegate(){

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

класс AppDelegate установлен в public, поэтому это не проблема с уровнем доступа.

используя objective-c в той же тестовой цели, она работает. Ниже простая инструкция:

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

в debuger говорит someDelegate это Встроенный.RawPointer. Не знаю, что это такое, я не знаком с низкого уровня.

3 ответов


я думаю, вы добавили AppDelegate.swift для целевых членов тестов.

когда вы сделаете это, AppName.AppDelegate и AppNameTests.AppDelegate становится разных классов. Затем:UIApplication.sharedApplication().delegate возвращает AppName.AppDelegate экземпляр, но вы пытаетесь бросить его в AppNameTests.AppDelegate тип. Это вызывает EXC_BAD_ACCESS.

вместо этого, вы должны импортировать его из своего модуля.

import UIKit
import XCTest
import AppName // <- HERE

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

и AppDelegate класс и его методы и свойства должны быть объявлены как public чтобы быть видимым из теста модуль.

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
    }

    // ...

еще раз, обязательно удалите AppDelegate.swift от тестовых целевых членов.


с обновлением Swift 2.0 продолжайте использовать решение rintaro. Но вы можете упростить это:

@testable импорт MyApp

тогда вам не нужно отмечать свой класс AppDelegate как открытый.


убедитесь, что ваш AppDelegate имеет "UIApplicationDelegate" в его декларации. То есть:

@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate {

и если вы делаете это для iOS,вам может потребоваться импортировать UIKit в верхней части этого файла.