17

我创建了一个包含核心数据模型的项目。该应用程序查找模型文件 (.momd) 并运行良好。

不幸的是,单元测试一直返回 null:

NSURL *dataModelURL = [[NSBundle mainBundle] URLForResource:@"myDataModel" withExtension:@"momd"];

我可以在主目标和单元测试目标的编译源目录中看到 myDataModel.xdatamodeld 文件夹和文件——但这似乎还不够。我在单元测试目标中还缺少什么?

谢谢,-路德

4

5 回答 5

35

不幸的是,单元测试目标不使用应用程序的主包,但它创建了一个特殊的单元测试包。因此,如果您需要在测试中使用捆绑资源(如 Core Data 模型),则需要解决该问题。

最简单和最灵活的解决方法是在测试代码中使用bundleForClass:方法。NSBundle该方法的参数可以简单地[self class]在您的测试中给出。这样您就可以重用此代码,而无需在多个项目中调整包标识符。

例子:

- (void)testBundleLocation
{
    NSBundle *bundle = [NSBundle bundleForClass:[self class]];
    NSURL *url = [bundle URLForResource:@"myDataModel" withExtension:@"momd"];
    ...
}
于 2012-04-18T11:31:02.670 回答
6

答案与捆绑包有关。单元测试目标不使用“主”包。它创建了自己的包,在我的例子中,它默认为“com.yourcompany.UnitTest”——直接来自 [Target]-info.plist。

更正后的解决方案如下所示:

NSBundle *bundle = [NSBundle bundleWithIdentifier:@"com.yourcompany.UnitTests"];
NSURL *url = [bundle URLForResource:@"myDataModel" withExtension:@"momd"];

谢谢

于 2011-04-14T19:40:12.080 回答
3

有类似的问题,我使用OCMock框架解决了,所以我不需要更改应用程序代码

@interface TestCase()
    @property (nonatomic, strong) id bundleMock;
@end

@implementation TestCase

- (void)setUp
{
    self.bundleMock = [OCMockObject mockForClass:[NSBundle class]];
    [[[self.bundleMock stub] andReturn:[NSBundle bundleForClass:[self class]]] mainBundle];
    [super setUp];
}

- (void)tearDown
{
    [self.bundleMock stopMocking];
    [super tearDown];
}
于 2014-02-26T12:25:47.830 回答
2

此方法将从任何目标获取您的捆绑包。但是,对于您添加的每个目标,您必须手动将 plist 捆绑标识符添加到identifiers数组中,因为无法以编程方式获取它。优点是您可以使用相同的代码来测试或运行应用程序。

+(NSBundle*) getBundle 
{
    NSBundle *bundle = nil;

    // try your manually set bundles
    NSArray *identifiers = [NSArray arrayWithObjects: @"com.your.application",
                                                      @"com.your.test",
                                                      nil];
    for(NSString *bundleId in identifiers) {
        bundle = [NSBundle bundleWithIdentifier:bundleId];
        if (bundle!=nil) break;
    }

    // try the main bundle
    if (bundle==nil) bundle = [NSBundle mainBundle];

    // abort
    assert(bundle!=nil && "Missing bundle. Check the Bundle identifier on 
           the plist of this target vs the identifiers array in this class.");

    return bundle;
}
于 2011-10-03T16:26:06.530 回答
0

我的问题确实是错误的Bundle!当我试图从/在框架内使用数据库时,我“只需”必须从相应的加载数据库Bundle

这是 Swift4 中的一些代码,使用MagicalRecord

// Load the bundle
let frameworkBundle = Bundle(for: AClassFromTheFramework.self)
let managedObjectModel = NSManagedObjectModel.mergedModel(from: [frameworkBundle])
// Use the new `managedObjectModel` by default
MagicalRecord.setShouldAutoCreateManagedObjectModel(false)
NSManagedObjectModel.mr_setDefaultManagedObjectModel(managedObjectModel)
// Load the database 
MagicalRecord.setupCoreDataStack(withAutoMigratingSqliteStoreNamed: "db.sqlite")

瞧!

于 2018-01-03T21:53:19.930 回答