У меня была такая же загадка. Мне нравится держать покрытие юнит-тестов на 100%, когда это возможно. Нет простого способа сгенерировать состояние органической ошибки. На самом деле, я не уверен, что текущая реализация четырех типов хранилищ, которые поставляются с Core Data, ever вызовет ошибку в ответ на executeFetchRequest: error. Но как это могло произойти в будущем, вот что я сделал:
У меня есть один файл с примерами модульных тестов, который посвящен проверке того, как мои классы обрабатывают ошибки, заполненные executeFetchRequest: error. Я определяю подкласс NSIncrementalStore, который всегда выдает ошибку во время запросов в файле реализации. [NSManagedObjectContext executeFetchRequest:error]
обрабатывается [NSPersistentStoreCoordinator executeRequest:withContext:error:]
, который обрабатывает [NSPersistentStore executeRequest:withContext:error:]
во всех магазинах. Вы можете заметить, что слово «выборка» пропадает при переходе к координатору - сохранения и запросы на выборку обрабатываются одним и тем же методом executeRequest:withContext:error:
. Таким образом, я получаю покрытие для тестирования на ошибки сохранения и выборки запросов, определяя NSPersistentStore, который всегда будет отвечать на сохранения и выборки с ошибками.
#define kErrorProneStore @"ErrorProneStore"
@interface ErrorProneStore : NSIncrementalStore
@end
@implementation ErrorProneStore
- (BOOL)loadMetadata:(NSError **)error
{
//Required - Apple's documentation claims you can omit setting this, but I had memory allocation issues without it.
NSDictionary * metaData = @{NSStoreTypeKey : kErrorProneStore, NSStoreUUIDKey : @""};
[self setMetadata:metaData];
return YES;
}
-(void)populateError:(NSError **)error
{
if (error != NULL)
{
*error = [[NSError alloc] initWithDomain:NSCocoaErrorDomain
code:NSPersistentStoreOperationError
userInfo:nil];
}
}
- (id)executeRequest:(NSPersistentStoreRequest *)request
withContext:(NSManagedObjectContext *)context
error:(NSError **)error
{
[self populateError:error];
return nil;
}
- (NSIncrementalStoreNode *)newValuesForObjectWithID:(NSManagedObjectID *)objectID
withContext:(NSManagedObjectContext *)context
error:(NSError **)error
{
[self populateError:error];
return nil;
}
- (id)newValueForRelationship:(NSRelationshipDescription *)relationship
forObjectWithID:(NSManagedObjectID *)objectID
withContext:(NSManagedObjectContext *)context
error:(NSError **)error
{
[self populateError:error];
return nil;
}
- (NSArray *)obtainPermanentIDsForObjects:(NSArray *)array
error:(NSError **)error
{
[self populateError:error];
return nil;
}
@end
Теперь вы можете создать базовый стек данных с помощью ErrorProneStore и быть уверенным, что ваши запросы на выборку вернут nil и заполнят параметр error.
- (void)testFetchRequestErrorHandling
{
NSManagedObjectModel * model = [NSManagedObjectModel mergedModelFromBundles:nil];
[NSPersistentStoreCoordinator registerStoreClass:[ErrorProneStore class]
forStoreType:kErrorProneStore];
NSPersistentStoreCoordinator * coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
NSManagedObjectContext * context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[context setPersistentStoreCoordinator:coordinator];
[coordinator addPersistentStoreWithType:kErrorProneStore
configuration:nil
URL:nil
options:nil
error:nil];
NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"AValidEntity"];
NSError * error;
[context executeFetchRequest:request
error:&error];
STAssertNotNil(error, @"Error should always be nil");
}