代码之家  ›  专栏  ›  技术社区  ›  Neal L

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

  •  2
  • Neal L  · 技术社区  · 14 年前

    我正在尝试开始对使用核心数据的应用程序进行单元测试。在我的单元第一次测试的设置方法中,我可以得到数据模型的路径,但由于某种原因不能将其转换为NSURL。

    我的设置方法是:

    - (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 回复  |  直到 10 年前
        1
  •  3
  •   Claus Broch    14 年前

    试用使用 [NSURL fileURLWithPath:path] 而不是构造URL

        2
  •  0
  •   Tyson Tune    14 年前

    仔细检查您是否看到一个名为datamodel.momd的目录,位于/users/neall/iphone apps/testapp/build/debug iphoneSimulator/logictests.octest/datamodel.momd。

    如果通过添加新文件添加XCDataModel文件…在Xcode中,您只有一个文件,它是datamodel.mom(没有尾随的d)。如果是这样,改变

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

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

    将立即解决您的问题。

    你想使用fileurlwithpath:克劳斯也建议使用。

    如果要在将来对模型进行版本控制,而当前只有.mom文件,请在Xcode中选择data model.xcdatamodel文件,然后转到“设计”->数据模型”->添加模型版本。这将强制创建包含datamodel.mom文件的datamodel.momd目录。您只需删除它添加到该目录中的新版本,原始测试就可以工作。

        3
  •  0
  •   knagode    12 年前

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

        4
  •  0
  •   user3857191    10 年前

    在2014年7月花了几个小时堆积如山之后,这篇文章是我找到工作解决方案的其中一部分。 我们设法打破了令人惊讶的脆弱(和神秘)机制,将源代码所在的包与运行单元测试的包相链接。此外,您可能有一个错误命名的XCDataModel。解释见注释:

    —(nsmanagedObjectContext*)getmanagedObjectContext
    {
    nsManagedObjectContext*moc=[[nsManagedObjectContext alloc]init];
    //将MyClass替换为数据模型中的类
    //实际上任何类都应该工作
    nsbundle*bundle=[nsbundle bundleforclass:[myclass class]];
    
    //您可以使用此行计算包的实际名称
    //在我的示例中,因为我的产品名称中有空格,所以它们被替换为“-”
    //(破折号)我无法从info.plist和构建设置中分辨出来。
    nsstring*ident=[bundle bundleIdentifier];
    
    
    //这将向您显示应用程序实际正在构建临时文件的位置
    //准确的位置会改变Xcode的每个版本或
    //这对于确定模型的名称很有用
    nsstring*bundlepath=[bundlepath];
    
    
    //这里用您的
    //不带扩展名的XcDataModel文件
    //有些教程会让您使用appname.xcdatamodel,其他人会简单地命名它
    //datamodel.xcdatamodel。
    //在任何情况下,如果路径和路径1返回空值,则检查
    //bundlepath,转到finder并按command-shift-g并粘贴
    //弹出窗口中的bundlepath。四处找一个你想要的妈妈或妈妈的文件!
    nsstring*路径=[束
    pathforresource:@“没有点xcdatamodel的\u模型的名称”
    类型:@“MOMD”];
    
    //如果上面的“path”和“path1”不是,则要使用此行
    nsstring*path1=[束
    pathforresource:@“没有点xcdatamodel的\u模型的名称”
    类型:@“妈妈”;
    
    //上面的路径行很简单,如果您有MOM或MOMD文件,就可以进行跟踪
    //在此适当替换
    nsurl*modelurl=[bundle urlforresource:@“没有点xcdatamodel的\u模型的名称”
    带扩展名:@“MOMD”];
    
    //其余为锅炉板:
    nsManagedObjectModel*mom=[[nsManagedObjectModel alloc]initWithContentsOfURL:modelURL];
    
    NSPersistentStoreCoordinator*PSC公司=
    [[nspersistentStoreCoordinator alloc]initWithManagedObjectModel:MOM];
    
    [PSC AddPersistentStoreWithType:NSIMemoryStoreType
    配置:nil url:nil选项:nil错误:nil];
    
    [MOC设置持续存储协调员:PSC];
    返回MOC;
    }
    < /代码> 
    
    

    以下是您如何使用上述上下文:

    —(void)testmystuff
    {
    
    nsManagedObjectContext*Context=[自我GetManagedObjectContext];
    myClass*myObj=[nsEntityDescription insertNewObjectforEntityForName:@“myClass”
    InManagedObjectContext:上下文];
    }
    < /代码> 
    
    

    最后一点需要注意的是,您可能还需要在构建阶段的“编译源代码”下添加源文件和xcmodel。不幸的是,这几乎随Xcode的每个版本而改变。对于Xcode 5:

    其中的几个部分让我找到了有效的解决方案。 我们设法打破了令人惊讶的脆弱(和神秘)机制,将源代码所在的包与运行单元测试的包相链接。此外,您可能有一个错误命名的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];
    }
    

    最后一点需要注意的是,您可能还需要在构建阶段的“编译源代码”下添加源文件和xcmodel。不幸的是,这几乎随Xcode的每个版本而改变。对于XCODE 5:

    xcode 5 build phases