【问题标题】:RestKit CoreData hangs during unit testRestKit CoreData 在单元测试期间挂起
【发布时间】:2013-10-30 21:57:10
【问题描述】:

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

它看起来与 Restkit 中的线程使用有关,因为我已经能够将其缩小到以下类和方法调用。基本上, performBlockAndWait 永远不会返回。我对客观 c 世界非常陌生(一般来说不是开发),所以任何帮助都将不胜感激。

Restkit 类: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 测试堆栈:

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

然后使用以下命令执行请求操作:

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 的示例测试设置和服务方法使用
  • 我真的应该问问你想用你的测试来证明什么 - 看起来你的服务器工作正常并且 RestKit 工作正常。单元测试不应该用于这些事情。
  • 计划更多地使用这些作为集成测试,以确保所涉及的系统正常运行,目标是通过每天运行几次的持续集成式构建过程实现自动化。另外,作为 xcode、objective-c 等的新手,我只想尝试了解测试支持的一般工作原理。将添加断言等,但在这一点上,我只是试图让方法执行并将记录插入CoreData。我同意,在“单元测试”的纯粹意义上,我不是孤立地测试服务。
  • 好的,所以在决定如何继续之前你需要做一些研究:google.co.uk/search?q=xcode+unittest+asynchronous

标签: ios unit-testing core-data restkit restkit-0.20


【解决方案1】:

我想出了一个使用 RestKit 提供的实用程序测试类之一的解决方案。

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

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

[observer waitForNotification];

我包装在一个实用方法中:

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

【讨论】:

  • 我也遇到了同样的问题。感谢您的解决方案。 =)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-28
  • 1970-01-01
相关资源
最近更新 更多