Тестовое приложение данных ядра

Как мне протестировать метод экземпляра 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 - это идентификатор , правильно?

5
задан Community 23 May 2017 в 10:33
поделиться