Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Setting up an in-memory Core Data stack for unit testing. This example uses Specta, but can be easily be adapted for XCTest.
#import <Specta.h>
#define EXP_SHORTHAND
#import <Expecta.h>
#import <CoreData/CoreData.h>
SpecBegin(CoreDataInMemorySetupExample)
__block NSManagedObjectContext *context;
beforeAll(^{
// ObjectModel from any models in app bundle
NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
// Coordinator with in-mem store type
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObjectModel];
expect([coordinator addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:nil]).notTo.beNil;
// Context with private queue
context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; // Choose your concurrency type, or leave it off entirely
context.persistentStoreCoordinator = coordinator;
// TODO: At this point you would pass the context var to your code...
});
afterAll(^{
context = nil;
});
it(@"some test here", ^AsyncBlock {
// TODO: write some expectations here which use the in-mem context set up above
});
SpecEnd
@aceontech

This comment has been minimized.

Copy link
Owner Author

commented Feb 7, 2014

A nicety would be to factor this code out into a category for convenience.
An example could be (NSManagedObjectContext+Testing.m):

@implementation NSManagedObjectContext (Testing)

+ (instancetype)testing_inMemoryContext:(NSManagedObjectContextConcurrencyType)concurrencyType error:(NSError **)error
{
    // ObjectModel from any models in app bundle
    NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];

    // Coordinator with in-mem store type
    NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObjectModel];
    [coordinator addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:error];

    // Context with private queue
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:concurrencyType];
    context.persistentStoreCoordinator = coordinator;

    return context;
}

@end
@marcuswu0814

This comment has been minimized.

Copy link

commented Dec 12, 2016

Hi @aceontech, this is a really good example for me to using Core data when I try to Unit test with managedObject.

But I still have some problem,

First, I didn't use Specta , I just using XCTestCase, and I move the code go to + (void)setUp and + (void)tearDown, is it correct?
(In official document, it said these two method just like Specta's beforeAll block and afterAll block.)

Second, I put the context = nil; in +(void)tearDown, sometimes cause crash, is it correct in ARC?

My code like the following attachment:

NSManagedObjectContext *inMemoryContext;

@interface ViewModelTest : XCTestCase

@end

@implementation ViewModelTest

#pragma mark - Setup

+ (void)setUp {
    inMemoryContext = [NSManagedObjectContext testing_inMemoryContext:NSPrivateQueueConcurrencyType error:nil];
}

+ (void)tearDown {
//    I comment this, crash go away 

//    if (inMemoryContext) {
//        inMemoryContext = nil;
//    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.