問題の核心は、Core Data モデルがテストで使用できないことです。そのため、読み取りプロパティをスタブしようとすると、そのメソッドは存在しません。Core Data は、実行時にプロパティ アクセサーを動的にインターセプトします。
モデルを利用できるようにするには、.xcdatamodeld が単体テスト ターゲットに含まれていることを確認し、テストでモデルを設定する必要があります。動的プロパティをモックできるかどうかはわかりませんが、テストで Core Data オブジェクトに対して CRUD 操作を行うのは簡単になるため、それらをモックする必要はありません。テストでモデルを初期化する 1 つの方法を次に示します。
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];
}