cocoa unit-testing core-data ocmock

cocoa - OCMock con problema de propiedades dinámicas de Core Data



unit-testing core-data (3)

La respuesta anterior no me satisfizo, porque no me gustaba crear un protocolo para eso. Así que descubrí que hay una manera más fácil de hacer eso. En lugar de

[[[mockItem stub] andReturn:@"fakepath.pdf"] PDFName]; // <-- throws exception here

Solo escribe

[[[mockItem stub] andReturn:@"fakepath.pdf"] valueForKey:@"PDFName"];

Estoy usando OCMock para burlarme de algunos objetos Core Data. Anteriormente, tenía las propiedades implementadas con los descriptores de acceso explícitos al estilo de Objective-C 1.0:

// -- Old Core Data object header @interface MyItem : NSManagedObject {} - (NSString *) PDFName; - (void) setPDFName:(NSString *)pdfName; @end // -- implementation provides generated implementations for both getter and setter

Ahora moví el código a Objective-C 2.0 y quiero aprovechar la nueva sintaxis de @property y las implementaciones de métodos generados dinámicamente para los objetos Core Data:

// -- New Core Data object header @interface MyItem : NSManagedObject {} @property (nonatomic, retain) NSString *PDFName; @end // -- Core Data object implementation @implementation MyItem @dynamic PDFName; @end

Sin embargo, ahora cuando creo un elemento simulado, no parece manejar las propiedades dinámicas:

// -- creating the mock item id mockItem = [OCMockObject mockForClass:[MyItem class]]; [[[mockItem stub] andReturn:@"fakepath.pdf"] PDFName]; // <-- throws exception here

El error se ve así:

Test Case ''-[MyItem_Test testMyItem]'' started. 2009-12-09 11:47:39.044 MyApp[82120:903] NSExceptionHandler has recorded the following exception: NSInvalidArgumentException -- *** -[NSProxy doesNotRecognizeSelector:PDFName] called! Stack trace: 0x916a4d24 0x92115509 0x97879138 0x978790aa 0x9090cb09 0x97820db6 0x97820982 0x10d97ff 0x10d9834 0x9782005d 0x9781ffc8 0x20103d66 0x20103e8c 0x20103642 0x20107024 0x20103642 0x20107024 0x20103642 0x20105bfe 0x907fead9 0x977e4edb 0x977e2864 0x977e2691 0x90877ad9 0xbf565 0xbf154 0x107715 0x1076c3 0x1082e4 0x89d9b 0x8a1e5 0x894eb 0x907e81c7 0x978019a9 0x978013da 0x907dd094 0x907ea471 0x9478c7bd 0x9478c1b9 0x94784535 0x5ede 0x326a 0x5 Unknown.m:0: error: -[MyItem_Test testMyItem] : *** -[NSProxy doesNotRecognizeSelector:PDFName] called!

¿Estoy haciendo algo mal? ¿Hay otra manera de burlarse de un objeto / Core Data con @dynamic prooperties?


También respondí a tu publicación cruzada en el foro de OCMock

Echa un vistazo a http://iamleeg.blogspot.com/2009/09/unit-testing-core-data-driven-apps.html .

Básicamente, sugiere abstraer la interfaz de su objeto Core Data a un protocolo y usar ese protocolo en lugar de la clase en la que pasa las instancias de su objeto Core Data.

Hago esto para mis objetos de datos centrales. Entonces puedes usar mockForProtocol:

id mockItem = [OCMockObject mockForProtocol:@protocol(MyItemInterface)]; [[[mockItem expect] andReturn:@"fakepath.pdf"] PDFName];

¡Funciona genial! También sugiere crear una implementación simulada de datos no básicos de la interfaz que simplemente sintetiza las propiedades:

@implementation MockMyItem @synthesize PDFName; @end ... id <MyItemInterface> myItemStub = [[MockMyItem alloc] init] autorelease]; [myItem setPDFName:@"fakepath.pdf"];

También he usado esto, pero no estoy seguro de que agregue algo sobre el enfoque mockForProtocol: / stub: y es una cosa más que mantener.


Una de las soluciones es usar un protocolo, que pretende sustituir su interfaz original, pero podría ser un poco pesado y lleva a una cantidad significativa de código que debería duplicar.

Personalmente, encontré una manera de hacerlo ligero:

Cree una categoría simple, por ejemplo, dentro de su archivo de prueba de unidad, justo antes de su clase de prueba de unidad:

@implementation MyItem(UnitTesing) - (NSString *)PDFName{return nil;}; @end

Además, puede mantenerlo en un archivo separado, pero asegúrese de que este archivo no sea parte de su objetivo de producción. Es por eso que prefiero guardarlo en el mismo archivo de prueba, donde quiero usarlo.

La gran ventaja de este método es que no debe copiar métodos creados por XCode para admitir relaciones. También puede incluir en esta categoría los métodos a los que llamará dentro de sus pruebas.

Sin embargo, hay algunas advertencias, por ejemplo, debe agregar otros métodos dentro de la categoría, para admitir a los definidores, cuando vaya a verificar cómo de correcto cambia su código las propiedades de su objeto administrado:

- (void)setPDFName:(NSString *)name{};