在单元测试中构建核心数据堆栈时出错

时间:2010-07-14 20:00:24

标签: iphone unit-testing core-data

我正在尝试开始使用Core Data进行单元测试。在我的单元第一次测试的setUp方法中,我可以获得我的数据模型的路径,但由于某种原因无法将其转换为NSURL。

我的setUp方法是:

- (void)setUp {

    NSBundle *bundle = [NSBundle bundleWithIdentifier:@"com.testcompany.LogicTests"];
    STAssertNotNil(bundle, @"Error finding bundle to create Core Data stack.");

    NSString *path = [bundle pathForResource:@"DataModel" ofType:@"momd"];
    STAssertNotNil(path, @"The path to the resource cannot be nil.");

    NSURL *modelURL = [NSURL URLWithString:path];
    STAssertNotNil(modelURL, @"The URL to the resource cannot be nil. (tried to use path:%@, modelURL is %@)", path, modelURL);

    ...

}

我得到的错误是:

/Users/neall/iPhone Apps/TestApp/UnitLogicTests.m:24:0 "((modelURL) != nil)" should be true. The URL to the resource cannot be nil. (tried to use path:/Users/neall/iPhone Apps/TestApp/build/Debug-iphonesimulator/LogicTests.octest/DataModel.momd, modelURL is (null))

我检查了文件系统,目录/Users/neall/iPhone Apps/TestApp/build/Debug-iphonesimulator/LogicTests.octest/DataModel.momd已存在。

我在这里缺少什么?

谢谢!

4 个答案:

答案 0 :(得分:3)

尝试使用[NSURL fileURLWithPath:path]来构建网址

答案 1 :(得分:0)

仔细检查您是否在/ Users / neall / iPhone Apps / TestApp / build / Debug-iphonesimulator / LogicTests.octest / DataModel.momd中看到名为DataModel.momd的目录。

如果您通过Xcode中的Add New File ...命令添加了一个xcdatamodel文件,那么您将只有一个文件,它将是DataModel.mom(没有尾随d)。如果是这种情况,请更改

NSString *path = [bundle pathForResource:@"DataModel" ofType:@"momd"];

NSString *path = [bundle pathForResource:@"DataModel" ofType:@"mom"];

将解决您的直接问题。

你想使用Claus建议的fileURLWithPath:

如果您希望将来对模型进行版本控制,并且您目前只有.mom文件,请在XCode中选择您的DataModel.xcdatamodel文件,然后转到Design - >数据模型 - >添加模型版本。这将强制创建包含DataModel.mom文件的DataModel.momd目录。您可以删除它添加到该目录中的新版本,并且您的原始测试将起作用。

答案 2 :(得分:0)

xcdatamodel也应添加到 项目 - >目标 - > “单元测试目标” - >构建阶段 - >编译来源

答案 3 :(得分:0)

在2014年7月花了几个小时后,这篇文章是几个部分导致我找到工作解决方案之一。 我们设法打破了令人惊讶的脆弱(和神秘)机制,它将源代码所在的bundle链接到运行单元测试的bundle。此外,您可能有一个名不副实的xcdatamodel。请参阅注释以获取解释:

-(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;
}

以下是您可以使用上述内容的方法:

-(void)testMyStuff
{

   NSManagedObjectContext* context=[self getManagedObjectContext];
   MyClass *myobj=[NSEntityDescription insertNewObjectForEntityForName:@"MyClass"   
   inManagedObjectContext:context];
}

最后请注意,您可能还需要在"编译源"下添加源文件和xcmod​​el。构建阶段。不幸的是,这几乎与每个版本的Xcode都有所不同。对于Xcode 5:

xcode 5 build phases