I am in the process of trying to get a test working for a service class that uses Restkit to perform various CoreData and JSON mapping operations related to the needs of our application. The service works fine when run via an iphone simulator deployment, but hangs when run via the context of a unit test.
It looks to be related to thread usage in Restkit as I have been able to narrow it down to the following class and method call. Basically, the performBlockAndWait never returns. I am very new to the objective c world (not to development in general) so any help would be greatly appreciated.
Restkit Class: RKFetchRequestManagedObjectCache
Method:
- (NSSet *)managedObjectsWithEntity:(NSEntityDescription *)entity
attributeValues:(NSDictionary *)attributeValues
inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
...
// test hangs on this fetch call
[managedObjectContext performBlockAndWait:^{
objects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
}];
I am setting up my CoreData test stack with the following:
NSBundle *bundle = [NSBundle bundleForClass:NSClassFromString(@"EventServiceTests")];
NSLog(@"Found bundle: %@", bundle);
NSString *bundlePath = [bundle pathForResource:@"EventDataModel" ofType:@"momd"];
NSLog(@"Creating model from path: %@", bundlePath);
NSURL *momURL = [NSURL URLWithString:bundlePath];
NSLog(@"URL for model: %@", momURL);
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
NSLog(@"Initializing the Core Data stack...");
[managedObjectStore createPersistentStoreCoordinator];
NSString* dataStorePath = [RKApplicationDataDirectory() stringByAppendingPathComponent: @"EventDataModel.dat"];
NSLog(@"Persistent store file path: %@", dataStorePath);
NSURL *storeUrl = [NSURL fileURLWithPath: dataStorePath];
if (![managedObjectStore.persistentStoreCoordinator addPersistentStoreWithType:NSBinaryStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
NSLog(@"Issue creating persitent store: %2@", error);
}
NSAssert(managedObjectStore.persistentStoreCoordinator.persistentStores, @"Failed to add persistent store: %@", error);
[managedObjectStore createManagedObjectContexts];
NSLog(@"Setting the default store shared instance to: %@", managedObjectStore);
[RKManagedObjectStore setDefaultStore:managedObjectStore];
NSLog(@"Configuring the object manager...");
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://eventconsole.eng.techtarget.com/"]];
objectManager.managedObjectStore = managedObjectStore;
NSLog(@"Setting shared manager instance to: %@", objectManager);
[RKObjectManager setSharedManager:objectManager];
Then executing the request operation using:
NSString* url = UPCOMING_EVENTS_URL_PATH;
NSLog(@"Attempting to get upcoming events from url: %@", url);
[[RKObjectManager sharedManager] getObjectsAtPath:url parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(@"Successfully loaded %@ upcoming events",
[NSString stringWithFormat:@"%ld", (unsigned long)[mappingResult count]] );
returnVal = TRUE;
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(@"Error loading upcoming events: %@", error);
returnVal = FALSE;
}
];
and the actual test code:
NSLog(@"Executing testLoadAttendees...");
[_eventService loadAttendees:@"2269"];
[NSThread sleepForTimeInterval:5.0f];
NSOperationQueue* queue = [RKObjectRequestOperation responseMappingQueue];
[queue waitUntilAllOperationsAreFinished];