Ios NSManagedObject的单元测试[GHUnit]

Ios NSManagedObject的单元测试[GHUnit],ios,unit-testing,nsmanagedobject,gh-unit,Ios,Unit Testing,Nsmanagedobject,Gh Unit,我是一名Java开发人员,我曾经将我的Java实体作为POJO进行测试。现在,对于Obj-C,我想对从NSManagedObject继承的实体做同样的操作(我使用CoreData进行持久化) 例如,我想测试我的客户实体,如下所示: -(void)myTest { Customer *customer = [Customer alloc] init]; customer.name = @"toto"; GHAssertEqualStrings(customer.name, @"toto", @""

我是一名Java开发人员,我曾经将我的Java实体作为POJO进行测试。现在,对于Obj-C,我想对从NSManagedObject继承的实体做同样的操作(我使用CoreData进行持久化)

例如,我想测试我的客户实体,如下所示:

-(void)myTest {
Customer *customer = [Customer alloc] init];
customer.name = @"toto";
GHAssertEqualStrings(customer.name, @"toto", @"");
}
但我遇到的错误是:

NSInvalidArgumentException 原因:-[Customers setName:]:无法识别的选择器已发送到实例…

因此,我已使用适当的数据库模式url加载了安装程序中的所有NSManagedObjectContext。现在,我将我的客户实例化为这样,它可以工作:

Customers *customer = [NSEntityDescription
insertNewObjectForEntityForName:kDataBaseCustomerKey inManagedObjectContext:ctx];
但这是测试“POJO”的合适方法吗?我想在不加载任何模型的情况下测试我的Customer类,因为在这种情况下,我不关心datamodel

谢谢你的建议


问候。

这取决于您测试的内容。从概念上把核心数据模型与现实生活中的实现分开有些困难;所以我通常在单元测试代码中构建自己的堆栈。另一方面,如果您真正测试的代码只依赖于
NSManagedObject
子类的实现,那么我认为您所概述的方法没有任何问题

作为参考,如果您对如何为单元测试重新创建堆栈感兴趣,以下是我的做法。(我刚刚注意到您使用的是
GHUnit
而不是
OCUnit
——应该是相同的,但是您可能需要确保该模型包含在
GHUnit
应用程序的捆绑资源中

创建一个继承自
SenTestCase
的类,并使用
NSInMemoryStoreType
在其中构建核心数据堆栈:

@implementation CCFCoreDataTestCase {
    NSManagedObjectModel *_mom;
    NSPersistentStoreCoordinator *_psc;
    NSManagedObjectContext *_moc;
    NSPersistentStore *_store;
}

@synthesize managedObjectContext = _moc;

- (void)setUp {
    [super setUp];

    NSArray *bundles = [NSArray arrayWithObject:[NSBundle bundleForClass:[self class]]];
    _mom = [NSManagedObjectModel mergedModelFromBundles:bundles];
    _psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:_mom];

    _store = [_psc addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:NULL];
    STAssertNotNil(_store,@"Unable to create in-memory store");

    _moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    [_moc setPersistentStoreCoordinator:_psc];
}

- (void)tearDown {
    [super tearDown];
    _mom = nil; _psc = nil; _moc = nil; _store = nil;
}
所有涉及核心数据的测试用例都应从该子类继承。如果您使用的是内存存储类型,并且在每次测试中构建和分解模型,则可以最小化任何依赖性,并从每个测试的未填充模型开始。当然,对于性能没有任何承诺

编辑:

我发现这篇文章在处理核心数据对象的单元测试时很有用-

编辑2:


Graham Lee(上述文章的作者)还有一篇关于不依赖模拟的单元测试核心数据对象的文章。请看,我上面描述的模式与他在第二个链接中所做的更为一致。

是的,我喜欢这个内存解决方案。谢谢你,它是有效的(即使使用GHUnit).但这意味着在我以前的解决方案中,我使用了“生产”包含现有数据的数据库?编辑:这篇文章很有意思,有了这个解决方案,我可以不用依赖核心数据堆栈就可以测试我的MockCustomer。但是..我不喜欢为每个实体创建一个模拟类。这不是一个繁重的解决方案吗?你怎么看?请参阅第二次编辑。我依赖于我描述的模式-creati在测试中使用轻量级堆栈。在您以前的解决方案中,至少在GHUnit中,我认为您实际上没有使用“生产”数据,这取决于您如何实例化
NSManagedObjectContext
——特别是因为GHUnit不知道您的应用程序的持久存储。好的,谢谢您的回答。我还将依赖model你提出了,但是Lee描述的模拟解决方案很有趣。