测试核心数据应用

时间:2011-03-18 03:23:15

标签: objective-c unit-testing core-data ocmock cedar-bdd

我应该如何测试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 storeChris 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。除了编写以下代码外,我还在NSManagedObject+Additions.m目标中添加了User.mSpec

#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

然后你获得奖励积分! :)如果参数应该是NSNumber,我似乎不应该将id强制转换为id,因为NSNumberid ,对吧?

1 个答案:

答案 0 :(得分:4)