問題的癥結在於您的Core Data模型在測試中不可用,所以當您嘗試對屬性讀取進行存根時,該方法不存在。核心數據在運行時動態攔截屬性訪問器。
要使您的模型可用,您需要確保您的.xcdatamodeld包含在您的單元測試目標中,並且您需要在測試中設置模型。我不確定你能否模擬動態屬性,但在測試中對核心數據對象執行CRUD操作變得微不足道,所以不需要嘲笑它們。下面就來初始化模型在測試中的一種方式:
static NSManagedObjectModel *model;
static NSPersistentStoreCoordinator *coordinator;
static NSManagedObjectContext *context;
static NSPersistentStore *store;
-(void)setUp {
[super setUp];
if (model == nil) {
@try {
NSString *modelPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"my-model" ofType:@"mom"];
NSURL *momURL = [NSURL fileURLWithPath:modelPath];
model = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
}
@catch (NSException *exception) {
NSLog(@"couldn't get model from bundle: %@", [exception reason]);
@throw exception;
}
}
coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
NSError *error;
store = [coordinator addPersistentStoreWithType: NSInMemoryStoreType
configuration: nil
URL: nil
options: nil
error: &error];
assertThat(store, isNot(nil));
context = [[NSManagedObjectContext alloc] init];
[context setPersistentStoreCoordinator:coordinator];
}
-(void)tearDown {
// these assertions ensure the test was not short-circuited by a failure to initialize the model
assertThat(model, isNot(nil));
assertThat(context, isNot(nil));
assertThat(store, isNot(nil));
assertThat(coordinator, isNot(nil));
NSError *error = nil;
STAssertTrue([coordinator removePersistentStore:store error:&error],
@"couldn't remove persistent store: %@", [error userInfo]);
[super tearDown];
}
或者,您也可以通過使用MagicalRecord顯著簡化事情。即使你沒有在你的應用中使用它,你也可以在測試中使用它來封裝所有的核心數據設置。這裏是我們的單元測試設置在MagicalRecord中的應用程序的樣子:
-(void)setUp {
[super setUp];
[MagicalRecordHelpers setupCoreDataStackWithInMemoryStore];
}
-(void)tearDown {
[MagicalRecordHelpers cleanUp];
[super tearDown];
}
我想我是在推翻這一個。我在內存存儲器中使用MagicalRecord進行測試,並且在每次測試之前重置db,就像您注意到的那樣。我應該剛剛使用託管對象而不是嘲笑它們。感謝您的徹底解答! –