2009-12-04 8 views
55

He estado desarrollando una aplicación para iPhone usando un modelo de dominio, y he pospuesto el aspecto de persistencia de la aplicación hasta ahora. Core Data parece ser una buena solución, ya que ya tengo un modelo bien definido pero me encuentro con un problema con mis pruebas unitarias existentes.¿Cómo puedo probar mis modelos una vez que estoy usando Core Data?

aquí es simple ejemplo de lo que tengo ahora:

- (void)test_full_name_returns_correct_string { 
    Patient *patient = [[Patient alloc] init]; 
    patient.firstName = @"charlie"; 
    patient.lastName = @"chaplin"; 
    STAssertTrue([[patient fullName] isEqualToString:@"charlie chaplin"], @"should have matched full name"); 
} 

¿Cómo puedo hacer este trabajo una vez que mi objeto paciente se extiende desde NSManagedObject y utiliza @dynamic para las propiedades de nombre y apellido?

¿Alguien más ha encontrado este tipo de esto con Core Data? Gracias.

Respuesta

84

Necesita construir una pila de Datos del Núcleo, dentro de cada método o en -setUp y luego derribarlo. El uso de un NSInMemoryPersistentStore mantendrá las cosas rápidas y en memoria para las pruebas de su unidad. Agregue @property (nonatomic,retain) NSManagedObjectContext *moc a su subclase TestCase. Entonces:

- (void)setUp { 
    NSManagedObjectModel *mom = [NSManagedObjectModel mergedModelFromBundles:[NSArray arrayWithObject:bundleContainingXCDataModel]]; 
    NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom]; 
    STAssertTrue([psc addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:NULL] ? YES : NO, @"Should be able to add in-memory store");  
    self.moc = [[NSManagedObjectContext alloc] init]; 
    self.moc.persistentStoreCoordinator = psc; 

    [mom release]; 
    [psc release]; 

} 

- (void)tearDown { 
    self.moc = nil; 
} 

Su método de ensayo, se parece a:

- (void)test_full_name_returns_correct_string { 
    Patient *patient = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.moc]; 

    patient.firstName = @"charlie"; 
    patient.lastName = @"chaplin"; 
    STAssertTrue([[patient fullName] isEqualToString:@"charlie chaplin"], @"should have matched full name"); 
} 

asumiendo que su entidad se denomina Person. Hubo una pérdida de memoria en su versión del método, por cierto; el paciente debe ser -release 'd en la versión no Core Data (insertNewObjectForEntityForName:managedObjectContext: devuelve una instancia autorrellenada).

+0

Gracias por la ayuda. Iré por esta ruta. Acerca de la pérdida de memoria, no me he molestado en limpiar la memoria en mis pruebas unitarias. Me parece más legible sin los lanzamientos. ¿Hay algún beneficio para evitar que las pruebas se filtren? –

+2

Si sus pruebas tienen fugas, es realmente difícil utilizar su suite de pruebas unitarias para probar su * otro * código de fugas. Instruments tiene un analizador de fugas que es básicamente inútil si oculta * reall * fugas con fugas innecesarias (pero intencionales) de las mismas clases en su código de prueba. –

+3

Creo que encontrará que el código de retención/liberación desaparece de la visión consciente después de un tiempo. Raramente lo noto más, a menos que falte. –

22

Utilicé la respuesta anterior de Barry Wark, pero tuve que hacer algunas modificaciones para que funcione con los proyectos actuales XCode5, iOS7.

La propiedad permanecido igual:

@interface SIDataTest : XCTestCase 
    @property (nonatomic,retain) NSManagedObjectContext *moc; 
@end 

La instalación tuvo que tenían realmente a cambiar en primer lugar a lo suelte, y posteriormente tener una URL modelo.

- (void)setUp 
{ 
    [super setUp]; 
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"SimpleInvoice" withExtension:@"momd"]; 
    NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 
    NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom]; 
    XCTAssertTrue([psc addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:NULL] ? YES : NO, @"Should be able to add in-memory store"); 
    self.moc = [[NSManagedObjectContext alloc] init]; 
    self.moc.persistentStoreCoordinator = psc; 
} 

Aquí es el caso de la prueba de muestra:

- (void)testCreateNew 
{ 
    Invoice *newInvoice = [NSEntityDescription insertNewObjectForEntityForName:@"Invoice" inManagedObjectContext:self.moc]; 
    newInvoice.dueDate = [NSDate date]; 
    NSString* title = [[NSString alloc] initWithFormat:@"Invoice %@", @112]; 
    newInvoice.title = title; 

    // Save the context. 
    NSError *error = nil; 
    if (![self.moc save:&error]) { 
     // Replace this implementation with code to handle the error appropriately. 
     // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
     XCTFail(@"Error saving in \"%s\" : %@, %@", __PRETTY_FUNCTION__, error, [error userInfo]); 
    } 
    XCTAssertFalse(self.moc.hasChanges,"All the changes should be saved"); 
} 
Cuestiones relacionadas