Unit Testing Core Data - exited abnormally with code 134
I am setting up unit testing for my core data app. I'm running into a strange problem in a pretty simple test. The error I'm getting is:
/Developer/Tools/RunPlatformUnitTests.include:451:0 Test rig '/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.0.sdk/Developer/usr/bin/otest' exited abnormally with code 134 (it may have cras开发者_JS百科hed).
The header for my unit tests is:
#import <SenTestingKit/SenTestingKit.h>
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#import "Unit.h"
@interface UnitLogicTests : SenTestCase {
NSManagedObjectContext *managedObjectContext;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
NSManagedObjectModel *managedObjectModel;
NSPersistentStore *persistentStore;
}
@end
The implementation is:
#import "UnitLogicTests.h"
@implementation UnitLogicTests
#pragma mark Setup and Teardown
- (void)setUp {
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles: nil] retain];
NSLog(@"model: %@", managedObjectModel);
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObjectModel];
persistentStore = [persistentStoreCoordinator addPersistentStoreWithType:NSInMemoryStoreType
configuration:nil
URL:nil
options:nil
error:NULL];
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator:persistentStoreCoordinator];
}
- (void)tearDown
{
[managedObjectContext release];
managedObjectContext = nil;
NSError *error = nil;
STAssertTrue([persistentStoreCoordinator removePersistentStore:persistentStore error:&error],
@"couldn't remove persistent store: %@", error);
persistentStore = nil;
[persistentStoreCoordinator release];
persistentStoreCoordinator = nil;
[managedObjectModel release];
managedObjectModel = nil;
}
#pragma mark -
#pragma mark Test Cases
- (void)testThatEnvironmentWorks
{
STAssertNotNil(persistentStore, @"no persistent store");
}
- (void)testNewUnitDefaults {
Unit *newUnit = [NSEntityDescription insertNewObjectForEntityForName:@"Unit"
inManagedObjectContext:managedObjectContext];
STAssertEquals(newUnit.floorNumber, 1, @"Default value for new Unit's floor number should be 1");
}
@end
If I omit the - (void)testNewUnitDefaults
test, then the build completes without errors, so something in that last test is throwing it for a loop. I am new to this, so any assistance would be greatly appreciated!
Thanks.
I got the same problem today, and I think Martin Brugger is right, but there is also an alternative method for getting bundle resrouce, if you could not get resource.
you can try get the bundle by
[NSBundle bundleForClass:[self class]]
here is my code to make the core data unit test work
NSBundle * bundle = [NSBundle bundleForClass:[self class]];
managedObjectModel_ = [NSManagedObjectModel mergedModelFromBundles:[NSArray arrayWithObject:bundle]];
NOTE: pls also ensure .xcdatamodel is included in your unit test target
put a @try .... catch block around your testcase.
I think loading the model with
[NSManagedObjectModel mergedModelFromBundles: nil]
did not work as expected
Using your code for initialization of the core data stack I got an exception
+entityForName: could not locate an entity named 'Unit' in this model.
Changing the model initialization to the following code works fine:
// set according to the identifier in your modeltest Info.plist
NSString* path = [[NSBundle bundleWithIdentifier:@"com.yourcompany.ModelTest"]
pathForResource:@"CoreDataUnitTest_DataModel"
ofType:@"mom"];
NSURL* modelURL = [NSURL URLWithString:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
Unit Tests with OCUnit sometimes are a bit tricky as only little information on errors is exposed.
After spending several hours stacking in July 2014 this post was one of several that in part led me to the working solution. We somehow managed to break the surprisingly fragile (and mysterious) mechanism that links the bundle that your source code lives in to the bundle that runs the unit test. Further you might have a misnamed xcdatamodel. See comments for explanations:
-(NSManagedObjectContext *) getManagedObjectContext
{
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init];
//Replace MyClass with class that is from your data model
//really any of your classes should work
NSBundle * bundle = [NSBundle bundleForClass:[MyClass class]];
//You can uses this line to figure you what your bundle is actually named
//In my case the because my PRODUCT_NAME had spaces in it they was replaced with '-'
//(dashes) and I couldn't divine it from the info.plist and the Build Settings.
NSString * ident =[bundle bundleIdentifier];
//This will show you where your app is actually out building temporary files
//The exact location appears to change every version or to of Xcode so
//this is useful for figuring out what your model is named
NSString * bundlePath =[bundle bundlePath];
//Here replace Name_of_model_without_the_dot_xcdatamodel with the name of your
//xcdatamodel file without an extension
//Some tutorials will have you use AppName.xcdatamodel others will simply name it
//DataModel.xcdatamodel.
//In any event if bothe path and path1 return null then check the
//bundlePath by going to Finder and pressing Command-Shift-G and pasting
//bundlePath into the pop-up. Look around for a mom or momd file thats the name you want!
NSString* path = [bundle
pathForResource:@"Name_of_model_without_the_dot_xcdatamodel"
ofType:@"momd"];
//If the above 'path' and 'path1' is not then you want to use this line instead
NSString* path1 = [bundle
pathForResource:@"Name_of_model_without the_dot_xcdatamodel"
ofType:@"mom"];
//the above path lines are simply so you can trace if you have a mom or a momd file
//replace here appropriately
NSURL *modelURL = [bundle URLForResource:@"Name_of_model_without the_dot_xcdatamodel"
withExtension:@"momd"];
//the rest is boiler plate:
NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSPersistentStoreCoordinator *psc =
[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
[psc addPersistentStoreWithType:NSInMemoryStoreType
configuration:nil URL:nil options:nil error:nil];
[moc setPersistentStoreCoordinator:psc];
return moc;
}
Here is how you might use the above context:
-(void)testMyStuff
{
NSManagedObjectContext* context=[self getManagedObjectContext];
MyClass *myobj=[NSEntityDescription insertNewObjectForEntityForName:@"MyClass"
inManagedObjectContext:context];
}
One final note you may also have to add your source files and xcmodel under the "Compile Sources" of build phases. This unfortunately changes with almost every version of Xcode. For Xcode 5:
精彩评论