MagicalRecordいいですね。
Mogenerator + MagicalRecordでCoreData入門を参考に試している最中です。
ですがXCTestを使う上でハマったことがあり、最適な手段を模索中です。
もっといい方法があればご教示ください。
問題点
XCTestでModelのテストをする場合
以下のようにsetup
,tearDown
を記述しメモリ上でCoreDataを使うように設定すると思います。参考:unit-testing-with-core-data
@interface SampleTests : XCTestCase
@end
@implementation SampleTests
- (void)setUp
{
[super setUp];
[MagicalRecord setupCoreDataStackWithInMemoryStore];
}
- (void)tearDown
{
[MagicalRecord cleanUp];
[super tearDown];
}
//省略
問題はアプリ部分であるAppDelegateにもMagicalRecordの初期化が記述されるということ。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[MagicalRecord setupAutoMigratingCoreDataStack];
return YES;
}
- (void)applicationWillTerminate:(UIApplication *)application
{
[MagicalRecord cleanUp];
}
で、Testを実行するとAppDelegateの中も実行されるので、
[MagicalRecord setupAutoMigratingCoreDataStack];
も実行されてしまい、CoreDataはファイルを使う設定にされてしまうようです。
で、テストが失敗するようになります。
対応策
テストを実行中はapplication:didFinishLaunchingWithOptions:
等は何もしないようにしてしまいます。
更に、コード上でStoryBoardを読むようにして、テスト中はStoryBoardも見に行かないようにします(initialViewcontrollerがCoreDataにアクセスしている場合を考慮)
プロジェクト設定のGeneral
->Deployment Info
->Main Interface
の中身を空欄にしておきます
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
BOOL inTests = (NSClassFromString(@"XCTest") != nil);
if (inTests) {
return YES;
}
[MagicalRecord setupAutoMigratingCoreDataStack];
//codeによるStoryBoard読み込みと表示
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
UIViewController *initialViewController = [storyboard instantiateInitialViewController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = initialViewController;
[self.window makeKeyAndVisible];
return YES;
}
//省略
- (void)applicationWillTerminate:(UIApplication *)application
{
BOOL inTests = (NSClassFromString(@"XCTest") != nil);
if (inTests) {
return;
}
[MagicalRecord cleanUp];
}