I have a pretty standard Xcode-generated interface for Core Data objects, namely these properties on my app delegate:
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
Now I’m writing application tests, but I want to use an in-memory database for core data that’s reset every time a test runs. I’ve figured out a way to do it, but it feels totally hinky:
- I have a static variable,
storeType, in the app delegate class. -persistentStoreCoordinatorsets it toNSSQLiteStoreTypeif it’snil. This will be the default value and, in production, the only value, ensuring that things work properly when running the app.- I make sure the the
DEBUGmacro is set for all debug builds (including for my App Tests target) -
If
DEBUGis set, define a method in the app delegate,-resetCoreData. The method looks like this:#ifdef DEBUG - (void)resetCoreData { // Testing, we want to use the in memory store. storeType = NSInMemoryStoreType; // Disconnect core data. __persistentStoreCoordinator = nil; __managedObjectContext = nil; // Set up defaults. [self configureCoreDataDefaults]; } #endifNote that it sets the static variable
storeTypetoNSInMemoryStoreType. The-configureCoreDataDefaultsmethod creates some managed objects that should always be present. -
In my app test base class, I have
-setupcall-resetCoreData:- (void)setUp { [super setUp]; [[[UIApplication sharedApplication] delegate] resetCoreData]; }
This gives me what I want: A fresh core data store with default objects created for every single test method.
But it’s annoying. I’ve essentially added knowledge of the testing environment to my app delegate, to make it behave differently when running app tests. Gross!
So, what’s a better way to do this? How do you do it?
I recommend creating a DAO or similar to isolate the Core Data setup. Then, using a category, you can define and use this “resetCoreData” in your test target.