iphone cocoa xcode unit-testing ocunit

iphone - Unit Test no puede encontrar el archivo de modelo de Core Data



cocoa xcode (5)

La respuesta tiene que ver con el paquete. Un objetivo de prueba de unidad no usa el paquete ''principal''. Crea su propio paquete que, en mi caso, dejó de forma predeterminada ''com.yourcompany.UnitTest'' - directamente del [Target] -info.plist.

La solución corregida se ve así:

NSBundle *bundle = [NSBundle bundleWithIdentifier:@"com.yourcompany.UnitTests"]; NSURL *url = [bundle URLForResource:@"myDataModel" withExtension:@"momd"];

Gracias

Creé un proyecto con un modelo de Core Data. La aplicación busca el archivo de modelo (.momd) y funciona perfectamente.

Desafortunadamente, la prueba de unidad sigue devolviendo nulo:

NSURL *dataModelURL = [[NSBundle mainBundle] URLForResource:@"myDataModel" withExtension:@"momd"];

Puedo ver la carpeta myDataModel.xdatamodeld y archivo tanto en el objetivo principal como en el directorio de fuentes de compilación del objetivo de prueba de la unidad, pero eso no parece ser suficiente. ¿Qué más me estoy perdiendo en el objetivo de la prueba de unidad?

Gracias, -Luther


Este método obtendrá su paquete de cualquier objetivo. Sin embargo, para cada objetivo que agregue, debe agregar manualmente el identificador de conjunto plist a la matriz de identifiers , porque no hay forma de obtenerlo mediante programación. La ventaja es que puede usar el mismo código para probar o ejecutar la aplicación.

+(NSBundle*) getBundle { NSBundle *bundle = nil; // try your manually set bundles NSArray *identifiers = [NSArray arrayWithObjects: @"com.your.application", @"com.your.test", nil]; for(NSString *bundleId in identifiers) { bundle = [NSBundle bundleWithIdentifier:bundleId]; if (bundle!=nil) break; } // try the main bundle if (bundle==nil) bundle = [NSBundle mainBundle]; // abort assert(bundle!=nil && "Missing bundle. Check the Bundle identifier on the plist of this target vs the identifiers array in this class."); return bundle; }


Desafortunadamente, un objetivo de prueba de unidad no usa el paquete principal de la aplicación, pero crea un paquete UnitTest especial. Por lo tanto, si necesita utilizar recursos agrupados (como un modelo de Datos centrales) dentro de sus pruebas, debe solucionar ese problema.

La solución más simple y más flexible sería usar el método bundleForClass: NSBundle dentro de su código de prueba. El parámetro para ese método puede ser simplemente dado por [self class] dentro de sus pruebas. De esta forma, puede reutilizar este código sin tener que ajustar los identificadores de paquetes en múltiples proyectos.

Ejemplo:

- (void)testBundleLocation { NSBundle *bundle = [NSBundle bundleForClass:[self class]]; NSURL *url = [bundle URLForResource:@"myDataModel" withExtension:@"momd"]; ... }


Tuve un problema similar, lo resolví utilizando el marco OCMock, por lo que no tuve que cambiar el código de la aplicación

@interface TestCase() @property (nonatomic, strong) id bundleMock; @end @implementation TestCase - (void)setUp { self.bundleMock = [OCMockObject mockForClass:[NSBundle class]]; [[[self.bundleMock stub] andReturn:[NSBundle bundleForClass:[self class]]] mainBundle]; [super setUp]; } - (void)tearDown { [self.bundleMock stopMocking]; [super tearDown]; }


¡Mi problema era, de hecho, el paquete equivocado! Como estaba tratando de usar una base de datos desde / dentro de un Framework I, ''simplemente'' tiene que cargar el db desde el Bundle correspondiente.

Aquí hay un código en Swift4 usando MagicalRecord :

// Load the bundle let frameworkBundle = Bundle(for: AClassFromTheFramework.self) let managedObjectModel = NSManagedObjectModel.mergedModel(from: [frameworkBundle]) // Use the new `managedObjectModel` by default MagicalRecord.setShouldAutoCreateManagedObjectModel(false) NSManagedObjectModel.mr_setDefaultManagedObjectModel(managedObjectModel) // Load the database MagicalRecord.setupCoreDataStack(withAutoMigratingSqliteStoreNamed: "db.sqlite")

¡Y voilá!