我已经创建了一个包含Core Data模型的项目。应用程序查找模型文件(.momd)并运行正常。
不幸的是,单元测试不断返回null:
NSURL *dataModelURL = [[NSBundle mainBundle] URLForResource:@"myDataModel" withExtension:@"momd"];
我可以在主目标和单元测试目标的Compile Sources目录中看到myDataModel.xdatamodeld文件夹和文件 - 但这似乎不够。我在单元测试目标中还缺少什么?
谢谢, -Luther
答案 0 :(得分:35)
不幸的是,单元测试目标不使用应用程序的主bundle,但它会创建一个特殊的UnitTest-bundle。因此,如果您需要在测试中使用捆绑资源(如核心数据模型),则需要解决该问题。
最简单,最灵活的解决方法是在测试代码中使用bundleForClass:
NSBundle
方法。该方法的参数可以在测试中由[self class]
简单地给出。这样,您可以重用此代码,而无需在多个项目中调整包标识符。
示例:
- (void)testBundleLocation
{
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSURL *url = [bundle URLForResource:@"myDataModel" withExtension:@"momd"];
...
}
答案 1 :(得分:6)
答案与捆绑包有关。单元测试目标不使用'main'包。它创建了自己的bundle,在我的例子中,默认为'com.yourcompany.UnitTest' - 直接来自[Target] -info.plist。
修正后的解决方案如下所示:
NSBundle *bundle = [NSBundle bundleWithIdentifier:@"com.yourcompany.UnitTests"];
NSURL *url = [bundle URLForResource:@"myDataModel" withExtension:@"momd"];
由于
答案 2 :(得分: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];
}
答案 3 :(得分: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;
}
答案 4 :(得分:0)
我的问题确实是错误的捆绑!当我试图在框架内/在框架内使用数据库时,我只是'必须从相应的Bundle
加载数据库!
以下是使用MagicalRecord
的Swift4中的一些代码:
// 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")
瞧!