【发布时间】:2011-03-18 03:23:14
【问题描述】:
我应该如何测试findByAttribute instance method I added to NSManagedObject?
一开始我想到了programmatically creating an independent Core Data stack as demonstrated by Xcode's Core Data Utility Tutorial。而且,在我搜索该文档时,我遇到了Core Data Fetch Request Templates,并认为也许我应该创建获取请求模板而不是创建我所做的方法,但它看起来不像 entityName 可以使用获取请求模板,可以吗?我可以在NSManagedObject 上创建一个获取请求模板,以便所有子类都可以使用它吗?嗯,但是我仍然需要entityName,而且我认为没有办法动态获取调用该方法的子类的名称。
无论如何,create an in-memory Core Data stack for testing 看起来是一个不错的解决方案,独立于生产核心数据堆栈。 @Jeff Schilling also recommends creating an in-memory persistent store。 Chris Hanson also creates a persistent store coordinator to unit test Core Data。这似乎类似于 Rails 有一个单独的数据库进行测试。但是,@iamleeg recommends removing the Core Data dependence。
您认为哪种方法更好?我个人更喜欢后者。
更新:我是unit testing Core Data with OCHamcrest and Pivotal Lab's Cedar。除了编写下面的代码之外,我还在Spec 目标中添加了NSManagedObject+Additions.m 和User.m。
#define HC_SHORTHAND
#import <Cedar-iPhone/SpecHelper.h>
#import <OCHamcrestIOS/OCHamcrestIOS.h>
#import "NSManagedObject+Additions.h"
#import "User.h"
SPEC_BEGIN(NSManagedObjectAdditionsSpec)
describe(@"NSManagedObject+Additions", ^{
__block NSManagedObjectContext *managedObjectContext;
beforeEach(^{
NSManagedObjectModel *managedObjectModel =
[NSManagedObjectModel mergedModelFromBundles:nil];
NSPersistentStoreCoordinator *persistentStoreCoordinator =
[[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:managedObjectModel];
[persistentStoreCoordinator addPersistentStoreWithType:NSInMemoryStoreType
configuration:nil URL:nil options:nil error:NULL];
managedObjectContext = [[NSManagedObjectContext alloc] init];
managedObjectContext.persistentStoreCoordinator = persistentStoreCoordinator;
[persistentStoreCoordinator release];
});
it(@"finds first object by attribute value", ^{
// Create a user with an arbitrary Facebook user ID.
NSNumber *fbId = [[NSNumber alloc] initWithInteger:514417];
[[NSEntityDescription insertNewObjectForEntityForName:@"User"
inManagedObjectContext:managedObjectContext] setFbId:fbId];
[managedObjectContext save:nil];
NSNumber *fbIdFound = [(User *)[User findByAttribute:@"fbId" value:(id)fbId
entityName:@"User"
inManagedObjectContext:managedObjectContext] fbId];
assertThatInteger([fbId integerValue], equalToInteger([fbIdFound integerValue]));
[fbId release];
});
afterEach(^{
[managedObjectContext release];
});
});
SPEC_END
如果你能告诉我为什么如果我不cast to (id) the fbId argument passed to findByAttribute 我明白了
warning: incompatible Objective-C types 'struct NSNumber *',
expected 'struct NSString *' when passing argument 2 of
'findByAttribute:value:entityName:inManagedObjectContext:' from
distinct Objective-C type
那么您将获得奖励积分! :) 如果参数应该是id,我似乎不必将NSNumber 转换为id,因为NSNumber 是id,对吧?
【问题讨论】:
-
+1 一个写得很好的问题。感谢您花时间撰写它。
-
第 47 行是哪一行?您的行号未显示在帖子的代码中。 ;-)
-
这是我打电话给
findByAttribute的地方。我取出“第 47 行”并用该描述替换它。
标签: objective-c unit-testing core-data ocmock cedar-bdd