CoreData在单元测试期间挂起

CoreData在单元测试期间挂起

本文介绍了RestKit CoreData在单元测试期间挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试获取一个测试工作的服务类,使用Restkit来执行与我们的应用程序的需求相关的各种CoreData和JSON映射操作。该服务通过一个iphone模拟器部署运行良好,但当通过单元测试的上下文运行时挂起。

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.

看起来与Restkit中的线程使用相关,因为我已经能够缩小到下面的类和方法调用。基本上,performBlockAndWait从不返回。

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类:RKFetchRequestManagedObjectCache

Restkit Class: RKFetchRequestManagedObjectCache

方法:

- (NSSet *)managedObjectsWithEntity:(NSEntityDescription *)entity
                attributeValues:(NSDictionary *)attributeValues
         inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext

...

    // test hangs on this fetch call
    [managedObjectContext performBlockAndWait:^{
        objects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
    }];

我使用以下设置我的CoreData测试栈:

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;
        }
 ];

和实际测试代码:

NSLog(@"Executing testLoadAttendees...");
[_eventService loadAttendees:@"2269"];
[NSThread sleepForTimeInterval:5.0f];
NSOperationQueue* queue = [RKObjectRequestOperation responseMappingQueue];
[queue waitUntilAllOperationsAreFinished];


推荐答案

我想出了一个解决方案,由RestKit提供的类。

I figured out a solution using one of the utility test classes provided by RestKit.

RKTestNotificationObserver *observer =
    [RKTestNotificationObserver
         notificationObserverForName:RKObjectRequestOperationDidFinishNotification
                              object:nil];
observer.timeout = 60;
[observer addObserver];

NSLog(@"Executing testLoadAttendees...");
[_eventService loadAttendees:@"2269"];

[observer waitForNotification];

我用一个实用程序方法包装:

which I wrapped in a utility method:

- (void)executeAndTimeoutAfterSeconds:(int) timeoutSeconds usingBlock:(void(^)())block
{
    RKTestNotificationObserver *observer =
        [RKTestNotificationObserver notificationObserverForName:RKObjectRequestOperationDidFinishNotification object:nil];
    [observer addObserver];
    observer.timeout = timeoutSeconds;
    block();
    [observer waitForNotification];
}

所以现在执行测试:

[self executeAndTimeoutAfterSeconds:60 usingBlock:^ {
    NSLog(@"Executing testLoadAttendees...");
    [_eventService loadAttendees:@"2269"];
}];

这篇关于RestKit CoreData在单元测试期间挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-05 15:04