Objective c 测试核心数据应用程序
我应该如何测试测试 起初,我想到了。而且,在我搜索该文档时,我偶然发现并认为也许我不应该创建我创建的方法,而是应该创建获取请求模板,但它看起来不像Objective c 测试核心数据应用程序,objective-c,unit-testing,core-data,ocmock,cedar-bdd,Objective C,Unit Testing,Core Data,Ocmock,Cedar Bdd,我应该如何测试测试 起初,我想到了。而且,在我搜索该文档时,我偶然发现并认为也许我不应该创建我创建的方法,而是应该创建获取请求模板,但它看起来不像entityName可以随获取请求模板而变化,是吗?我是否可以在NSManagedObject上创建一个获取请求模板,以便所有子类都可以使用它?嗯,但是我仍然需要一个entityName,而且我认为没有办法动态获取调用该方法的子类的名称 无论如何,看起来一个好的解决方案是,独立于生产核心数据堆栈。这似乎类似于Rails有一个单独的数据库进行测试。但是
entityName
可以随获取请求模板而变化,是吗?我是否可以在NSManagedObject
上创建一个获取请求模板,以便所有子类都可以使用它?嗯,但是我仍然需要一个entityName
,而且我认为没有办法动态获取调用该方法的子类的名称
无论如何,看起来一个好的解决方案是,独立于生产核心数据堆栈。这似乎类似于Rails有一个单独的数据库进行测试。但是
你认为哪种方法更好?我个人更喜欢后者
更新:我很高兴。除了编写下面的代码外,我还将NSManagedObject+Additions.m
和User.m
添加到Spec
目标中
#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
然后您将获得额外积分!:)如果参数应该是
id
,我似乎不应该将NSNumber
转换为id
,因为NSNumber
是id
,是吗?我的个人哲学是,如果测试不测试真实事物,那么测试就不是测试,所以我对任何孤立测试片段的方法都不屑一顾。尽管它在许多情况下都能工作,特别是在过程代码中,但在复杂的代码中,例如在核心数据对象图中,它可能会失败
核心数据中的大多数故障点都来自于错误的数据模型,例如,缺少一个相互关系,因此图形失去平衡,并且存在孤立对象。测试坏图的唯一方法是创建一个已知的图,然后对代码进行压力测试,看看它是否能够找到并操作图中的对象
要实施这种类型的测试,我将执行以下操作:
Person
对象的firstName
属性值为John
,此方法将返回23462中的任意一个人实体。我看不出这一点。我认为您是在用过程SQL术语思考问题。这将导致在处理对象图管理器(如核心数据)时出现混乱。)
更新:
我猜您的错误是由编译器查看谓词中值的用法并假设它必须是NSString对象引起的。当您以字符串格式删除对象时,如谓词使用的字符串格式:
,返回的实际值是包含des结果的NSString对象对象的scription
方法。因此,对编译器而言,谓词实际上如下所示:
[NSPredicate predicateWithFormat:@"%K == %@", (NSString *)attribute, (NSString *)value]
…因此,当它向后工作时,它将在value
参数中查找NSString,尽管从技术上讲它不应该这样做。这种id的使用实际上不是最佳做法,因为它将接受任何类,但实际上您并不总是知道实例的-description
方法返回的描述字符串是什么
正如我上面所说,你在这里有一些概念上的问题。当你在下面的评论中说:
我的目的是要制定一个方法
类似于ActiveRecord的find_by_
动态查找器
…您从错误的角度处理核心数据。Active Record主要是围绕SQL的对象包装器,使现有SQL Server与Ruby on Rails更容易集成。因此,它主要由过程SQL概念控制
这与核心数据所使用的方法完全相反。核心数据首先是一个对象图管理系统,用于创建模型视图控制器应用程序设计的模型层。因此,对象就是一切。例如,甚至可能有没有属性的对象,只有关系。这些对象可能有非常复杂的beh这在SQL甚至Active record中都是不存在的
很可能有任意数量的对象具有完全相同的属性。这使得您试图创建的方法毫无价值和危险,因为您永远不知道将返回哪个对象。这使得它成为“混乱”方法。如果您有
[NSPredicate predicateWithFormat:@"%K == %@", (NSString *)attribute, (NSString *)value]