Как мне протестировать метод экземпляра findByAttribute
, который я добавил в NSManagedObject
?
Сначала я подумал о программном создании независимого стека Core Data, как продемонстрировано в учебном пособии Xcode Core Data Utility . И, ища эту документацию, я наткнулся на Core Data Fetch Request Templates и подумал, что, возможно, вместо создания метода, который я сделал, я должен сделать шаблоны запросов fetch, но не похоже, что entityName
может быть изменено с помощью шаблона запроса на выборку, не так ли? Могу ли я создать шаблон запроса на выборку для NSManagedObject
, чтобы все подклассы могли его использовать? Хм, но тогда мне все равно понадобится entityName
, и я не думаю, что есть способ динамически получить имя подкласса, который вызвал метод.
В любом случае, похоже, что хорошее решение - на создать стек Core Data в памяти для тестирования , независимый от производственного стека Core Data. @Jeff Schilling также рекомендует создать постоянное хранилище в памяти . Крис Хэнсон также создает постоянного координатора хранилища для модульного тестирования Core Data . Это похоже на то, как в Rails есть отдельная база данных для тестирования. Но, @iamleeg рекомендует удалить зависимость Core Data .
Какой, по вашему мнению, подход лучше? Лично я предпочитаю последнее.
ОБНОВЛЕНИЕ: Я модульное тестирование Core Data с помощью OCHamcrest и Pivotal Lab's Cedar . В дополнение к написанию кода ниже я добавил NSManagedObject + Additions.m
и User.m
в цель Spec
.
#define HC_SHORTHAND
#import
#import
#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)
аргумент fbId
, переданный в 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
, потому что NSNumber
- это идентификатор
, правильно?