2014-11-15 1 views
7

Ich versuche Unit-Test in Swift zu verwenden, um einige der realen Anwendung Verhalten zu testen. Wenn ich versuche, de UIApplicationDelegate zu meinem AppDelegate von meiner Testfunktion ich bekam und EXC_BAD_ACCESS Ausnahme. Unter dem Testcode:UIApplication.sharedApplication(). Delegate als AppDelegate verursacht EXC_BAD_ACCESS mit es auf schnelle Einheit Test

func testGetAppDelegate(){ 

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

AppDelegate Klasse ist öffentlich so eingestellt, dass es kein Problem von der Berechtigungsebene.

Mit objective-c im gleichen Testziel funktioniert es. Unterhalb der einfachen Anweisung:

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

Der debuger sagt someDelegate ist ein Builtin.RawPointer. Ich weiß nicht, was das ist, ich bin nicht vertraut mit Low-Level-Details.

Antwort

10

Ich denke, Sie haben AppDelegate.swift zu den Testzielelementen hinzugefügt.

Wenn Sie das tun, wird AppName.AppDelegate und AppNameTests.AppDelegate verschiedene Klassen. Dann gibt UIApplication.sharedApplication().delegateAppName.AppDelegate Instanz zurück, aber Sie versuchen, es in AppNameTests.AppDelegate Typ zu konvertieren. Das verursacht EXC_BAD_ACCESS.

Stattdessen müssen Sie es von Ihrem Anwendungsmodul importieren.

import UIKit 
import XCTest 
import AppName // <- HERE 

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

Und AppDelegate Klasse und ihre Methoden und Eigenschaften müssen public deklariert werden sichtbar von Testmodul zu sein.

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 
    } 

    // ... 

Wieder Seien Sie sicher, AppDelegate.swift von den Test-Zielelemente zu entfernen.

+0

Sie haben richtig geraten, vielen Dank. Ich muss diese Informationen immer noch verdauen, um herauszufinden, was der richtige Ansatz zum Testen ist, einige Beiträge schlagen vor, das zu tun, was ich tat, aber das, was ich tat, war das Problem. – ByteArtisan

+1

Einige unabhängige Klassen wie 'DateUtility' können direkt zum Testziel hinzugefügt werden. Aber die Klassen, die an die Hauptanwendung gebunden sind, wie beispielsweise AppDelegate oder CoreData, können nicht getestet werden, ohne sie vom Hauptanwendungsmodul zu importieren. Für die "Unit-Tests" ist das direkte Hinzufügen also OK. Aber für die "Anwendungstests", importieren Sie sie. – rintaro

+0

Ich versuche zu implementieren, was Sie hier gesagt haben, aber ich habe immer noch Probleme. Mein Code befindet sich unter: http: // stackoverflow.com/questions/28042105/swift-dynamic-cast-gescheitert-swift-dynamiccastclassunconditional –

0

Stellen Sie sicher, dass Ihr AppDelegate "UIApplicationDelegate" in seiner Deklaration hat. Das heißt:

@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate {

Und wenn Sie tun dies für iOS, you might need to import UIKit at the top of this file.

+0

Die Deklaration ist genau wie Sie es zeigen und den Test UIKit an der Spitze importieren. – ByteArtisan

+0

Und du hast eine saubere und wieder aufgebaut? –

+0

Ja, ich lösche sogar den derivatedData-Ordner. – ByteArtisan

2

Verwenden Sie mit dem Swift 2.0-Update weiterhin die rintaro-Lösung. Aber man kann es durch Vereinfachung:

@testable Import MeineAnw

Dann brauchen Sie nicht Ihre AppDelegate Klasse als öffentlich zu markieren.

Verwandte Themen