2014-11-15 9 views
7

Sto provando a utilizzare unit test in swift per testare il comportamento dell'applicazione reale. Quando provo a trasmettere il numero UIApplicationDelegate al mio AppDelegate dalla mia funzione di test, ho ricevuto un'eccezione EXC_BAD_ACCESS. Sotto il codice di prova:UIApplication.sharedApplication(). Delegate come AppDelegate causa EXC_BAD_ACCESS che lo utilizza sul test rapido dell'unità

func testGetAppDelegate(){ 

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

AppDelegate la classe è impostata su pubblico, quindi non è un problema dal livello di accesso.

Utilizzando l'obiettivo-c nello stesso target di prova funziona. Sotto le semplici istruzioni:

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

Il debugger dice che SomeDelegate è un Builtin.RawPointer. Non so di cosa si tratta, non ho familiarità con i dettagli di basso livello.

risposta

10

Penso che tu abbia aggiunto AppDelegate.swift ai membri di destinazione dei test.

Quando si esegue questa operazione, AppName.AppDelegate e AppNameTests.AppDelegate diventano classi diverse. Quindi, UIApplication.sharedApplication().delegate restituisce l'istanza AppName.AppDelegate, ma si sta provando a trasmetterla al tipo AppNameTests.AppDelegate. Ciò causa EXC_BAD_ACCESS.

Invece di quello, è necessario importarlo dal modulo dell'applicazione.

import UIKit 
import XCTest 
import AppName // <- HERE 

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

E, AppDelegate classe ed i suoi metodi e proprietà devono essere dichiarate come public per essere visibile dal modulo di test.

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 
    } 

    // ... 

Anche in questo caso, assicurarsi di rimuovere AppDelegate.swift dai membri di destinazione di prova.

+0

Hai indovinato, molte grazie. Devo ancora digerire queste informazioni per scoprire quale sia l'approccio giusto per i test, alcuni post suggeriscono di fare come stavo facendo, ma il modo in cui stavo facendo era il problema. – ByteArtisan

+1

Alcune classi indipendenti, ad esempio 'DateUtility', possono essere aggiunte direttamente al target dei test. Ma le classi legate all'applicazione principale, come ad esempio 'AppDelegate' o CoreData related, non possono essere testabili senza importarle dal modulo dell'applicazione principale. Per così dire, per i "test unitari", l'aggiunta diretta è OK. Ma per i "test delle applicazioni", importali. – rintaro

+0

Sto cercando di implementare quello che hai detto qui, ma ho ancora problemi. Il mio codice si trova all'indirizzo: http: // stackoverflow.it/questions/28042105/swift-dynamic-cast-failed-swift-dynamiccastclassunconditional –

0

Assicurati che il tuo AppDelegate abbia "UIApplicationDelegate" nella sua dichiarazione. Cioè:

@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate {

E se si sta facendo questo per iOS, you might need to import UIKit at the top of this file.

+0

La dichiarazione è esattamente come lo si punta e il test importa UIKit in alto. – ByteArtisan

+0

E hai fatto anche un clean & rebuild? –

+0

Sì, ho persino cancellato la cartella derivataData. – ByteArtisan

2

Con l'aggiornamento Swift 2.0, continuare a utilizzare la soluzione di rintaro. Ma si può semplificare da:

@testable MyApp importazione

Allora non c'è bisogno di marcare la classe AppDelegate come pubblico.

Problemi correlati