Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do UnitTests with CoreData?

starting form the CoreData template, I have built an iphone app that uses CoreData to manipulate a Data Model. Works so far...

Now I decided, I need some "unit" tests to check if the core data model is manipulated correctly (so far I have only done manual checks and checked the database directly with CoreDataEditor). I have followed

http://developer.apple.com/library/ios/#documentation/Xcode/Conceptual/iphone_development/135-Unit_Testing_Applications/unit_testing_applications.html

on how to set up UnitTests in Xcode. This works so far for both Logic and Application Tests. However, I cannot get the "unit" tests working with a CoreData backend (it doesn't find my data model and I don't know what to include or link etc...)

Is there a pointer/description on how to do "unit" testing of a core data iphone app?

PS: I know testing with the database back end is not strictly speaking "unit" testing. I don't care whether the test is on the simulator with the real application (ApplicationTesting) or if it is just a core data backend specifically for the unit tests (LogicTest) that I would fill with some test objects during setUp.

EDIT: I have found How to unit test my models now that I am using Core Data? and http://chanson.livejournal.com/115621.html but now I ran into the problem described in iPhone UnitTesting UITextField value and otest error 133 ... well, except that i have error code 134 :-((( Any ideas?

like image 672
naeger Avatar asked Apr 13 '11 09:04

naeger


1 Answers

OK. I got it working ...

  1. Create LogicTests as described here (section setting up Logic Testing): http://developer.apple.com/library/ios/#documentation/Xcode/Conceptual/iphone_development/135-Unit_Testing_Applications/unit_testing_applications.html

  2. Manually add the CoreData.framework to the newly created Target for the Logic Tests: Drag it from the application target to the logic test target (folder "link binary with libraries).

  3. Right-click on your *.xcdatamodeld and select Get Info -> Targets. Select the Logic Tests target (for some strange reason the actual application target was not selected in my case ... but that works)

  4. In your unit test class (you created in step 1: LogicTests.m) add the following method:

    - (void) setUp {
    
       NSArray *bundles = [NSArray arrayWithObject:[NSBundle bundleForClass:[self class]]];
       NSManagedObjectModel *mom = [NSManagedObjectModel mergedModelFromBundles:bundles];
       STAssertNotNil(mom, @"ManangedObjectModel ist nil");
    
       NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
       STAssertTrue([psc addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:NULL] ? YES : NO, @"Should be able to add in-memory store");    
    
       self.context = [[NSManagedObjectContext alloc] init];
       self.context.persistentStoreCoordinator = psc;
    
       [mom release];
       [psc release];
    }
    

Now you have a Logic Test with Core Data support set up. The logic testing is done in isolation (without simulator) by building the LogicTests target. For this a temporary in-memory database is created. In your test methods you can now do something like:

- (void) testStuff {    
     NSManagedObject *managedObj = [NSEntityDescription insertNewObjectForEntityForName:@"Account" inManagedObjectContext:self.context];

     [managedObj setValue:[NSNumber numberWithInt:90000] forKey:@"id"];

     NSError *error = nil;
     if (![self.context save:&error]) {
         STFail(@"Fehler beim Speichern: %@, %@", error, [error userInfo]);
     }
}

Hope this helps.... Have fun!

like image 196
naeger Avatar answered Oct 11 '22 02:10

naeger