2010-05-16 15 views
6

Entonces ... Estoy intentando configurar las pruebas de unidad en mi aplicación de iPhone, pero tengo algunos problemas. Estoy intentando probar mis clases de modelo, pero heredan directamente de NSManagedObject. Estoy seguro de que esto es un problema, pero no sé cómo evitarlo.Modelo de prueba de unidades Clases que heredan de NSManagedObject

Todo es la construcción y en funcionamiento como se esperaba, pero me sale este error cuando se llama a cualquier método en la clase que soy prueba:

Unknown.m:0:0 unrecognized selector sent to instance 0xc2b120

Si sigo this structure para crear mi objeto en mis pruebas que termino con otro error por completo, pero todavía no me ayuda.

Si instanciar mi modelo como este:

entry = [[TimeEntry alloc] 
     initWithEntity:nil 
     insertIntoManagedObjectContext:nil]; 

Entonces termino con este error en tiempo de ejecución:

An NSManagedObject of class 'TimeEntry' must have a valid NSEntityDescription.

si trato de esta manera:

entry = [[TimeEntry alloc] init]; 

Luego termino con este error:

unrecognized selector sent to instance 0xc2b120

Y si sigo el patrón laid out here:

model = [[NSManagedObjectModel mergedModelFromBundles: nil] retain]; 
NSLog(@"model: %@", model); 
coord = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: model]; 
store = [coord addPersistentStoreWithType: NSInMemoryStoreType 
          configuration: nil 
             URL: nil 
            options: nil 
            error: NULL]; 
ctx = [[NSManagedObjectContext alloc] init]; 
[ctx setPersistentStoreCoordinator: coord]; 

entry = (TimeEntry *)[NSEntityDescription insertNewObjectForEntityForName:@"TimeEntry" inManagedObjectContext:ctx]; 

Entonces me sale este error:

could not locate an entity named 'TimeEntry' in this model.

Básicamente mi pregunta es la siguiente: ¿cómo puedo probar una clase que hereda de NSManagedObject?

+0

favor editar su pregunta para mostrar cómo se está instanciar la subclase NSManagedObject. –

+0

Bien, avíseme si eso ayuda. Gracias. –

Respuesta

7

Para crear una instancia de un NSManagedObject, necesita una entidad. Por lo tanto, lo primero que intentó, ya sea pasando nil para la entidad o usando bare -init (que no es compatible con NSManagedObject) - no funcionó. Estás haciendo lo correcto mediante el uso de -[NSEntityDescription insertNewObjectForEntityForName:inManagedObjectContext:] para crear el objeto, sólo tiene que:

  1. Asegúrese de que la entidad TimeEntry existe en el modelo de datos.
  2. Asegúrese de que la entidad TimeEntry esté asociada con la clase TimeEntry en su modelo de datos.
  3. Asegúrate de que tus pruebas carguen realmente tu modelo de datos.

Tenga en cuenta que a menos que desee probar guardar/eliminar validación, generalmente no necesitará agregar una tienda persistente a su coordinador. (Y si está usando una tienda persistente SQLite en su aplicación, le sugiero que también use una en sus pruebas, los diferentes tipos de tiendas persistentes tienen diferentes características de rendimiento y consultas compatibles.)

Para garantizar que su modelo de datos esté cargado, le resultará mucho más fructífero, creo que realmente debe especificar la URL para cargarlo, en lugar de esperar que lo haya colocado en el lugar correcto y que -mergedModelFromBundles: hará lo correcto. Lo convertiría en miembro del objetivo del paquete de prueba de la unidad, por lo que se compilará en los recursos del paquete de prueba de la unidad. De esta forma, puede usar un método NSBundle apropiado para obtener la ruta o la URL.

Por último, va a querer configurar la configuración de la pila de persistencia de Core Data, el modelo, el coordinador de tienda persistente y el contexto de reutilización, en un método -setUp en su caso de prueba. O en un método -setUp de una clase base de caso de prueba, si desea crear más de una clase de caso de prueba. (Lo mismo vale para desmontaje de la pila de persistencia y -tearDown métodos, por supuesto.)

4

creé una muestra para un entorno de prueba de Datos Básicos en github http://github.com/mbrugger/CoreDataDependentProperties/blob/master/LPAutomatedObserving/Tests/ManagedObjectSenTestCase.m

Heredar los casos de prueba de ManagedObjectSenTestCase.m/h y ajustar las dos líneas siguientes con su objetivo de prueba identificador del paquete y los datos de nombre de modelo

 NSBundle* bundle = [NSBundle bundleWithIdentifier:@"com.yourcompany.ModelTest"]; 

    NSString* path = [bundle pathForResource:@"DataModel" ofType:@"mom"]; 

ejemplos de código:

-(void) setUp 
{ 
    pool = [[NSAutoreleasePool alloc] init]; 

    NSMutableSet *allBundles = [[[NSMutableSet alloc] init] autorelease]; 
    [allBundles addObjectsFromArray:[NSBundle allBundles]]; 

    NSBundle* bundle = [NSBundle bundleWithIdentifier:@"com.yourcompany.ModelTest"]; 

    NSString* path = [bundle pathForResource:@"DataModel" 
                          ofType:@"mom"]; 

    NSURL* modelURL = [NSURL URLWithString:path]; 
    self.model = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] autorelease]; 

    self.coordinator = [[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.model] autorelease]; 


    LPManagedObjectContext* tempContext = [[[NSManagedObjectContext alloc] init] autorelease]; 


    [tempContext setPersistentStoreCoordinator:coordinator]; 
    [tempContext setRetainsRegisteredObjects:YES]; 

    self.context = tempContext; 
} 

    -(void) tearDown 
{ 
    NSLog(@"BEGIN: ManagedObjectSenTestCase tearDown"); 
    @try 
    { 
     self.context= nil; 
     self.model = nil; 
     self.coordinator = nil; 
     [pool release]; 
     pool = nil; 
    } 
    @catch (NSException * e) 
    { 
     NSLog(@"%@",e); 
     NSLog(@"%@", [e callStackSymbols]); 
     NSLog(@"context reset failed!"); 
     @throw(e); 

    } 
    NSLog(@"END: ManagedObjectSenTestCase tearDown"); 
} 

Este ejemplo crea la pila de datos centrales y puede insertar entidades en el contexto creado para la prueba.

0

Tuve el mismo problema. Eventualmente me di cuenta de que no podía recuperar mi modelo, pero al ser un novato en el desarrollo de iPhone no pude encontrar la manera de cargarlo desde una URL según la sugerencia de Chris.

cargarlo desde el haz que las pruebas se ejecutan a partir es lo que funcionó para mí:

@implementation WhenWorkingWithATiming 

Timing *timing; 

NSManagedObjectModel *model; 
NSPersistentStoreCoordinator *coordinator; 
NSManagedObjectContext *context; 


- (void) setUp { 
    NSArray *bundles = [NSArray arrayWithObject:[NSBundle bundleForClass:[self class]]]; 
    model = [[NSManagedObjectModel mergedModelFromBundles:bundles] retain]; 
    NSLog(@"Model: %@", model); 

    coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model]; 
    context = [[NSManagedObjectContext alloc] init]; 
    [context setPersistentStoreCoordinator:coordinator]; 

    timing = (Timing *)[NSEntityDescription insertNewObjectForEntityForName:@"Timing" inManagedObjectContext:context]; 
} 

- (void) tearDown { 
    [context rollback]; 
    [context release]; 
    [coordinator release]; 
    [model release]; 
} 

- (void) testThatTimingIsInitialised { 
    STAssertNotNil(timing, @"should have a timing"); 
} 

@end 
Cuestiones relacionadas