I am Java developer and I used to test my Java entity as POJO. Now, with Obj-C, I would like to do the same for my entity that inherit from NSManagedObject (I use CoreData for the persistence).
For example I would like to test my Customer entity as that :
-(void)myTest {
Customer *customer = [Customer alloc] init];
customer.name = @"toto";
GHAssertEqualStrings(customer.name, @"toto", @"");
}
But the error I encountered is :
NSInvalidArgumentException Reason: -[Customers setName:]: unrecognized selector sent to instance ...
So I have loaded all the NSManagedObjectContext in the setUp with the appropriate database schema url. Now I instantiate my customer as that and it works :
Customers *customer = [NSEntityDescription
insertNewObjectForEntityForName:kDataBaseCustomerKey inManagedObjectContext:ctx];
But is it an appropriate way to test a 'POJO'? I would like to test my Customer class without any model loading, because in this case I do not care of the datamodel.
Thank you for your suggestions.
Regards.
It depends on what you're testing. It's somewhat difficult to conceptually separate out the Core Data model from the implementation in real-life; so I usually build my own stack in unit test code. On the other hand, if you are really testing code that depends only on implementation of the NSManagedObject
subclasses, there's nothing wrong with the approach that I think you've outlined.
For reference, if you're interested in how to recreate the stack for the unit test, here's how I do it. (I just noticed that you are using GHUnit
instead of OCUnit
- it should be the same, but you'll probably need to make sure that the model is included in the bundle resources for the GHUnit
app.
Create a class that inherits from SenTestCase
and build your Core Data stack there with an NSInMemoryStoreType
:
@implementation CCFCoreDataTestCase {
NSManagedObjectModel *_mom;
NSPersistentStoreCoordinator *_psc;
NSManagedObjectContext *_moc;
NSPersistentStore *_store;
}
@synthesize managedObjectContext = _moc;
- (void)setUp {
[super setUp];
NSArray *bundles = [NSArray arrayWithObject:[NSBundle bundleForClass:[self class]]];
_mom = [NSManagedObjectModel mergedModelFromBundles:bundles];
_psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:_mom];
_store = [_psc addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:NULL];
STAssertNotNil(_store,@"Unable to create in-memory store");
_moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_moc setPersistentStoreCoordinator:_psc];
}
- (void)tearDown {
[super tearDown];
_mom = nil; _psc = nil; _moc = nil; _store = nil;
}
All of your test cases that touch Core Data should inherit from this subclass. Given that you are using an in-memory store type and you build and tear down the model with each test, you minimize any dependencies and start with an unpopulated model for each test. No promises regarding performance, of course.
EDIT:
I found this post helpful when working with unit testing of Core Data objects - Unit testing Core Data-driven apps
EDIT 2:
Graham Lee (the author of the post above) has another post about unit testing Core Data objects that doesn't rely on mocking. See this one The pattern that I describe above is more consistent with what he does in the second link.