2012-02-21 24 views
5

Theo NSManagedObjectContext Class Documentation ...Core Data Testing Unit - Không chắc chắn làm thế nào để kích hoạt trường hợp lỗi trong executeFetchRequest: lỗi:

- (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.

Tôi đang cố gắng để tạo ra một thử nghiệm đơn vị cho tình hình "nếu một lỗi xảy ra, trả về nil. "

Tôi muốn tránh xa việc sử dụng OCMock (hoặc phân lớp NSManagedObjectContext để ghi đè phương thức executeFetchRequest: error:) bởi vì tôi có một cách dễ dàng để đảm bảo lỗi của phương thức này. Cho đến nay thử nghiệm đơn vị của tôi đã đọc ...

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

Có cách nào đơn giản để kích hoạt yêu cầu tìm nạp trở lại không?

Trả lời

4

Tôi đã có cùng một câu hỏi hóc búa. Tôi muốn giữ mức độ kiểm tra đơn vị ở mức 100% bất cứ khi nào có thể. Không có cách dễ dàng để tạo ra một điều kiện lỗi hữu cơ. Trong thực tế, tôi không chắc chắn việc thực hiện hiện tại của 4 loại cửa hàng đi kèm với dữ liệu lõi sẽ bao giờ kích hoạt một lỗi để đáp ứng với executeFetchRequest: lỗi. Nhưng vì nó có thể xảy ra trong tương lai, đây là những gì tôi đã làm:

Tôi có một tệp thử nghiệm đơn vị dành riêng để xác thực cách các lớp xử lý lỗi của tôi được điền bởi executeFetchRequest: error. Tôi định nghĩa một phân lớp của NSIncrementalStore luôn luôn tạo ra một lỗi trong các yêu cầu trong tệp thực hiện. [NSManagedObjectContext executeFetchRequest:error] được xử lý bởi [NSPersistentStoreCoordinator executeRequest:withContext:error:] xử lý [NSPersistentStore executeRequest:withContext:error:] trên tất cả các cửa hàng. Bạn có thể nhận thấy rằng từ "tìm nạp" giảm khi bạn di chuyển đến điều phối viên - lưu và tìm nạp yêu cầu được xử lý theo cùng phương thứcexecuteRequest:withContext:error:. Vì vậy, tôi nhận được bảo hiểm để thử nghiệm chống lại lỗi lưu và tìm nạp yêu cầu bằng cách xác định NSPersistentStore sẽ luôn phản hồi để lưu và tìm nạp có lỗi.

#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 

Bây giờ bạn có thể xây dựng ngăn xếp Dữ liệu cốt lõi bằng cách sử dụng ErrorProneStore và được đảm bảo yêu cầu tìm nạp của bạn sẽ trả về 0 và điền thông số lỗi.

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

Rất thông minh! Tôi tò mò tại sao bạn không phân lớp 'NSManagedObjectContext' và ghi đè' executeFetchRequest: error: '. Đó là giải pháp duy nhất tôi đã đưa ra bởi vì tôi đã không tìm ra cách để lôi kéo hữu cơ trường hợp lỗi. Subclassing plus ghi đè bên trái tôi với cách tiếp cận hơi rõ ràng hơn (mặc dù có giới hạn hơn). – edelaney05

+2

Tôi không phân lớp trực tiếp ngữ cảnh vì không có dữ liệu nào trong dữ liệu chính dễ dàng như vậy. [NSManagedObjectContext executeFetchRequest: error] được xử lý bởi [NSPersistentStoreCoordinator executeRequest: withContext: error:] xử lý [NSPersistentStore executeRequest: withContext: error:] trên tất cả các cửa hàng hiện tại. Bạn có thể nhận thấy rằng từ "tìm nạp" giảm khi bạn di chuyển đến điều phối viên - lưu và tìm nạp các yêu cầu được xử lý bởi cùng phương thức executeRequest: withContext: error :. Vì vậy, tôi nhận được bảo hiểm để thử nghiệm chống lại lỗi lưu và tìm nạp yêu cầu bằng cách xác định ErrorProneStore. –

+0

Cảm ơn sự thấu hiểu! – edelaney05

0

Theo tôi, việc sử dụng OCMock dễ dàng hơn nhiều.

- (void)testCountForEntityFetchError { 
    id mockContext =[OCMockObject partialMockForObject:self.context]; 

    [[[mockContext stub] andCall:@selector(stubbedExecuteFetchRequest:error:) onObject:self] countForFetchRequest:OCMOCK_ANY error:[OCMArg setTo:nil]]; 

    // Your code goes here 
} 

- (NSArray *)stubbedExecuteFetchRequest:(NSFetchRequest *)request error:(NSError **)error { 
    *error = [NSError errorWithDomain:@"CRTest" code:99 userInfo:nil]; 
    return nil; 
} 
Các vấn đề liên quan