Skip to content

Instantly share code, notes, and snippets.

@aceontech
Created February 7, 2014 10:04
Show Gist options
  • Save aceontech/8860058 to your computer and use it in GitHub Desktop.
Save aceontech/8860058 to your computer and use it in GitHub Desktop.
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
Copy link
Author

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
Copy link

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