2015-05-15 17 views
9

Ho bisogno di test di unità (XCTest) alcuni dei miei metodi che includono riferimento ai modelli CoreData.swift - Unit test CoreData (+ MagicalRecord) trigger di trigger EXC_BAD_ACCESS

La seguente riga eseguire correttamente:

var airport: AnyObject! = Airport.MR_createEntity() 

(lldb) po airport <Airport: 0x7fcf54216940> (entity: Airport; id: 0x7fcf54216a20 <x-coredata:///Airport/t1D3D08DA-70F9-4DA0-9487-BD6047EE93692> ; data: { 
    open = nil; 
    shortName = nil; 
    visible = nil; }) 

mentre la riga seguente attiva un EXC_BAD_ACCESS:

var airport2: Airport = Airport.MR_createEntity() as! Airport 

(lldb) po airport2 
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x0). 
The process has been returned to the state before expression evaluation. 

Nessun segno di questo errore con il mio obiettivo principale. La configurazione è: oggetti modello in entrambi gli obiettivi, classe prefissata da @objc(MyModel), nessuno spazio dei nomi nei modelli di classe nel mio xcdatamodel

Qualche idea di cosa sta succedendo qui?

+0

Hai contrassegnato i tuoi metodi e proprietà come pubblici nella tua classe Airport?Il controllo rapido degli accessi potrebbe essere il problema – railwayparade

+0

Appena provato, stesso risultato :( – Yaman

+0

Ho finito per creare entità manualmente senza RM stenografia per l'inserimento ... –

risposta

3

Giusto, quindi ho finalmente raggiunto il fondo di questo e non è bello. In questo caso, esiste effettivamente un problema radar poiché sembra che un bug con il compilatore Swift non riconosca il cast di ManagedObject nelle destinazioni di test. Quindi aggiungi la tua voce per il rumore

Partendo con un soggetto definito come segue:

@objc(Member) 
class Member: NSManagedObject {  
    @NSManaged var name: String 
} 

ho scritto una semplice classe di test in cui creo un MO in 3 modi diversi:

La prima due falliti:

let context = NSManagedObjectContext.MR_defaultContext() 

func testMagicalRecordCreation() { 
    let m = Member.MR_createInContext(context) as? Member 
    XCTAssertNotNil(m, "Failed to create object")//fails 
} 

func testEntityDescriptionClassCreation() { 
    let m2 = NSEntityDescription.insertNewObjectForEntityForName("Member", inManagedObjectContext: context) as? Member 
    XCTAssertNotNil(m2, "Failed to create object")//fails 
} 

E poi un successo

func testManualMOCreation() { 
    let ent = NSEntityDescription.entityForName("Member", inManagedObjectContext: context)! 
    let m3 = Member(entity: ent, insertIntoManagedObjectContext: context) 
    XCTAssertNotNil(m3, "Failed to create object") 
} 

Ciò significa che al momento hai due opzioni. Scrivi i tuoi test in Objective-C; oppure creare un metodo di utilità per inserire oggetti di prova in un contesto usando i mezzi che ho mostrato sopra.

Theres un bel post su questo comportamento here

ho finito per usare un'estensione NSManagedObjectContext per essere utilizzato in modo esplicito nei test Swift:

extension NSManagedObjectContext { 
    func insertTestEntity<T: NSManagedObject>(entity: T.Type) -> T { 
     let entityDescription = NSEntityDescription.entityForName(NSStringFromClass(T.self), inManagedObjectContext: self)! 
     return T(entity: entityDescription, insertIntoManagedObjectContext: self) 
    } 
} 

E potrebbe essere utilizzato in questo modo:

func testConvenienceCreation() { 
    let m4 = context.insertTestEntity(Member) 
    XCTAssertNotNil(m4, "Failed to create object") 
} 

Altre informazioni su questo tipo di approccio here

0

Ci sono due modi per rendere le vostre classi di applicazioni Swift a disposizione del target di test:

  1. rendere il vostro classi di applicazione pubblica - questo include tutte le variabili, costanti, e la funzione che si desidera testare

  2. Aggiungi l'applicazione Swift al tuo obiettivo Test. Questo è abbastanza semplice da fare.

+0

questo non è ciò che l'OP sta chiedendo ... –