ios - 核心数据单元测试 - 不确定如何在 executeFetchRequest :error: 中触发错误案例

标签 ios unit-testing core-data

根据 NSManagedObjectContext Class Documentation ...

- (NSArray *)executeFetchRequest:(NSFetchRequest *)request error:(NSError **)error

Return Value

An array of objects that meet the criteria specified by request fetched from the receiver and from the persistent stores associated with the receiver’s persistent store coordinator. If an error occurs, returns nil. If no objects match the criteria specified by request, returns an empty array.

我正在尝试为“如果发生错误,返回 nil”的情况创建单元测试。

我不想使用 OCMock(或子类化 NSManagedObjectContext 来覆盖 executeFetchRequest:error: 方法),因为我认为有一种简单的方法可以确保此方法失败。到目前为止,我的单元测试读取...

- (void)testReportingCoreDataErrorToDelegate
{
    NSManagedObjectContext *badContext = [[NSManagedObjectContext alloc] init];

    [bcc setManagedObjectContext:badContext];
    [bcc fetchFromCoreData];
    STAssertTrue([mockDelegate didReceiveCoreDataError], @"This never asserts, it fails because the fetch request couldn't find an entity name - i.e. no managed object model");
}

是否有一种简单的方法来触发返回 nil 的提取请求?

最佳答案

我遇到了同样的难题。我喜欢尽可能将单元测试覆盖率保持在 100%。没有简单的方法来生成有机错误条件。事实上,我不确定 Core Data 随附的 4 种存储类型的当前实现是否会曾经触发错误以响应 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 并填充错误参数。

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

关于ios - 核心数据单元测试 - 不确定如何在 executeFetchRequest :error: 中触发错误案例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9382151/

相关文章:

ios - 如何从关系实体中进行简单的获取? swift

ios - 点击动态创建的 UIButtons 崩溃应用程序

c# - 在 Akkanet 中使用依赖注入(inject)时如何传递 actor 依赖

java - 如何更改 Mockito 中字符串的默认返回值?

unit-testing - 如何防止在 Visual Studio 2012 中自动执行单元测试?

ios - 静态 NSManagedObject 将保留在内存中

ios - 核心数据锁因为合并?

ios - 有人可以为我澄清这个 block 吗?

ios - 钛iOS : tab groups images not showing

ios - 验证应用内购买收据的目的是什么?