单元测试模型继承自NSManagedObject的类

Mat*_*ker 6 unit-testing core-data objective-c

所以...我正试图在我的iPhone应用程序中设置单元测试,但我遇到了一些问题.我正在尝试测试我的模型类,但它们直接从NSManagedObject继承.我确定这是一个问题,但我不知道如何绕过它.

一切都按预期构建和运行但是在我正在测试的类上调用任何方法时出现此错误:

Unknown.m:0:0 unrecognized selector sent to instance 0xc2b120

如果我按照这个结构在我的测试中创建我的对象,我最终会得到另一个错误,但它仍然无法帮助我.

如果我像这样实例化我的模型:

entry = [[TimeEntry alloc]
        initWithEntity:nil
        insertIntoManagedObjectContext:nil];
Run Code Online (Sandbox Code Playgroud)

然后我在运行时结束这个错误:

An NSManagedObject of class 'TimeEntry' must have a valid NSEntityDescription.

如果我这样尝试:

entry = [[TimeEntry alloc] init];
Run Code Online (Sandbox Code Playgroud)

然后我最终得到了这个错误:

unrecognized selector sent to instance 0xc2b120

如果我遵循这里列出的模式:

model = [[NSManagedObjectModel mergedModelFromBundles: nil] retain];
NSLog(@"model: %@", model);
coord = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: model];
store = [coord addPersistentStoreWithType: NSInMemoryStoreType
                            configuration: nil
                                      URL: nil
                                  options: nil 
                                    error: NULL];
ctx = [[NSManagedObjectContext alloc] init];
[ctx setPersistentStoreCoordinator: coord];

entry = (TimeEntry *)[NSEntityDescription insertNewObjectForEntityForName:@"TimeEntry" inManagedObjectContext:ctx];
Run Code Online (Sandbox Code Playgroud)

然后我收到这个错误:

could not locate an entity named 'TimeEntry' in this model.

基本上我的问题是:我如何测试从NSManagedObject继承的类?

Chr*_*son 7

为了实例化NSManagedObject,您需要一个实体.因此,您首次尝试 - 要么nil为实体传递,要么使用裸-init(NSManagedObject不支持) - 都不起作用.通过使用-[NSEntityDescription insertNewObjectForEntityForName:inManagedObjectContext:]创建对象,您正在做正确的事情,您只需要:

  1. 确保数据模型中存在实体TimeEntry.
  2. 确保实体 TimeEntry与数据模型中的 TimeEntry 相关联.
  3. 确保您的测试实际加载了您的数据模型.

请注意,除非您特别想要测试保存/删除验证,否则通常不需要向协调器添加持久性存储.(如果您在应用程序中使用SQLite持久性存储,我强烈建议您在测试中使用一个;不同的持久性存储类型具有不同的性能特征和支持的查询.)

为了确保加载您的数据模型,您会发现实际指定加载它的URL会更有成效,而不是仅仅希望您将它放在正确的位置并且这样-mergedModelFromBundles:做是正确的.我将它作为单元测试包目标的成员,因此它被编译到您的单元测试包的资源中.这样你就可以使用适当的NSBundle方法来获取它的路径或URL.

最后,您将要-setUp在测试用例的方法中设置Core Data持久性堆栈 - 模型,持久性存储协调器和临时上下文.或者在-setUp测试用例基类的方法中,如果要创建多个测试用例类.(-tearDown当然,对于持久性堆栈和方法的拆除也是如此.)