Ho un app Swift che utilizza NSFetchedResultsController
per recuperare List
oggetti da archivio permanente:Come unità-test NSFetchedResultsController a Swift
let fetchedResultsController: NSFetchedResultsController = ...
var error : NSError?
fetchedResultsController.performFetch(&error)
if let error = error {
NSLog("Error: \(error)")
}
let lists: [List] = fetchedResultsController.fetchedObjects! as [List]
NSLog("lists count = \(lists.count)")
for list: List in lists {
NSLog("List: \(list.description)")
}
e funziona come previsto, io sono sempre List
oggetti descrizioni stampate al console. Vorrei scrivere alcuni test unitari per la mia app, quindi ho creato la classe che estende XCTestCase
. Il codice viene compilato senza problemi, i test vengono eseguiti, ma sfortunatamente non sono in grado di recuperare gli oggetti in quel contesto.
tutto io sono sempre nella console è conteggio di List
oggetti e un errore fatale:
lists count = 59
fatal error: NSArray element failed to match the Swift Array Element type
rizzati dalla linea:
for list: List in lists {
Sono abbastanza sicuro di avere obiettivi configurati correttamente, come posso creare l'oggetto List
e inserirlo nel contesto dell'oggetto gestito senza problemi dal codice sorgente della mia app e dal codice sorgente del test dell'unità. L'unico problema che sto vivendo è con il recupero dall'unità di test. Mi chiedo perché il recupero funzioni quando si esegue l'app nel simulatore e fallisce quando viene eseguito durante il test dell'unità.
Tutte le idee su ciò che potrebbe essere sbagliato saranno apprezzate.
Aggiornamento:
Per essere più specifici come la mia implementazione sembra, qui è esempio di codice completo che sto giocando con:
var error: NSError? = nil
let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
let applicationDocumentsDirectory = urls[urls.count-1] as NSURL
let modelURL = NSBundle.mainBundle().URLForResource("CheckLists", withExtension: "momd")!
let managedObjectModel = NSManagedObjectModel(contentsOfURL: modelURL)
var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)
let url = applicationDocumentsDirectory.URLByAppendingPathComponent("CheckLists.sqlite")
if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil, error: &error) == nil {
NSLog("Error1: \(error)")
abort()
}
var managedObjectContext = NSManagedObjectContext()
managedObjectContext.persistentStoreCoordinator = coordinator
let fetchRequest = NSFetchRequest()
fetchRequest.entity = NSEntityDescription.entityForName("List", inManagedObjectContext: managedObjectContext)
fetchRequest.sortDescriptors = [ NSSortDescriptor(key: "name", ascending: true) ]
let fetchedResultsController = NSFetchedResultsController(
fetchRequest: fetchRequest,
managedObjectContext: managedObjectContext,
sectionNameKeyPath: nil,
cacheName: "ListFetchedResultsControllerCache"
)
fetchedResultsController.performFetch(&error)
if let error = error {
NSLog("Error2: \(error)")
abort()
}
let fetchedObjects: [AnyObject]? = fetchedResultsController.fetchedObjects
if let fetchedObjects = fetchedObjects {
NSLog("Fetched objects count: \(fetchedObjects.count)")
for fetchedObject in fetchedObjects {
NSLog("Fetched object: \(fetchedObject.description)")
}
}
else {
NSLog("Fetched objects array is nil")
}
let fetchedLists: [List]? = fetchedResultsController.fetchedObjects as? [List]
if let fetchedLists = fetchedLists {
NSLog("Fetched lists count: \(fetchedLists.count)")
for fetchedList in fetchedLists {
NSLog("Fetched list: \(fetchedList.description)")
}
}
else {
NSLog("Fetched lists array is nil")
}
Quando eseguo dal codice sorgente del mio app, eseguendo l'app nel simulatore, l'output della console è simile al seguente:
Fetched objects count: 3
Fetched object: <CheckLists.List: 0x7a6866f0> (entity: List; id: 0x7a686020 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p2> ; data: {
name = "List 1";
})
Fetched object: <CheckLists.List: 0x7a686930> (entity: List; id: 0x7a686030 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p1> ; data: {
name = "List 2";
})
Fetched object: <CheckLists.List: 0x7a686970> (entity: List; id: 0x7a686040 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p3> ; data: {
name = "List 3";
})
Fetched lists count: 3
Fetched list: <CheckLists.List: 0x7a6866f0> (entity: List; id: 0x7a686020 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p2> ; data: {
name = "List 1";
})
Fetched list: <CheckLists.List: 0x7a686930> (entity: List; id: 0x7a686030 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p1> ; data: {
name = "List 2";
})
Fetched list: <CheckLists.List: 0x7a686970> (entity: List; id: 0x7a686040 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p3> ; data: {
name = "List 3";
})
Tuttavia, quando eseguo questo codice da un unit test, sto ottenendo questo risultato:
Fetched objects count: 3
Fetched object: <CheckLists.List: 0x7a07df50> (entity: List; id: 0x7a07d7e0 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p2> ; data: {
name = "List 1";
})
Fetched object: <CheckLists.List: 0x7a07e190> (entity: List; id: 0x7a07d7f0 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p1> ; data: {
name = "List 2";
})
Fetched object: <CheckLists.List: 0x7a07e1d0> (entity: List; id: 0x7a07d800 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p3> ; data: {
name = "List 3";
})
Fetched lists array is nil
Spero che sia più facile capire dove si trova il problema. In qualche modo, questa affermazione:
let fetchedLists: [List]? = fetchedResultsController.fetchedObjects as? [List]
produce una matrice di List
oggetti quando app viene eseguito nel simulatore, ma fallisce producendo nil
quando eseguito dal test di unità.
Il file del modello di oggetto ("mamma") è incluso nel pacchetto di test? Ed è la configurazione del file del modello per utilizzare la sottoclasse 'Elenco' per l'entità dell'elenco? – MrAlek
@MrAlek - Non sono sicuro che il mio file '.momd' sia incluso nel bundle di test. Sto creando un modello del genere: 'NSManagedObjectModel (NSBundle.mainBundle(). URLForResource (" CheckLists ", withExtension:" momd ")!)' E funziona sia per il target principale che per il target di test. Potresti essere più specifico? – Darrarski
@MrAlek - Nel mio file '.xcdatamodeld' ho impostato la classe corretta per l'entità' List'. Posso persino creare una nuova entità nei miei test unitari e inserirla nel contesto. Rimane nel database quando il contesto viene salvato. – Darrarski