2010-02-15 1 views
4

Я просто разбираюсь в концепциях TDD и насмехается, и я сталкиваюсь с проблемой с точки зрения правильности. У меня есть лист, который падает и позволяет пользователю создать новый основной объект данных и сохранить его в хранилище данных. Я не уверен, что я использую лучший подход к его тестированию.Метод тестирования контроллера с данными OCMock и Core

- (IBAction)add:(id)sender 
{ 
    NSString *itemName = [self.itemNameTextField stringValue]; 
    SGItem *newItem = [NSEntityDescription insertNewObjectForEntityForName:kItemEntityName inManagedObjectContext:[self managedObjectContext]]; 
    newItem.name = itemName; 

    NSError *error = nil; 
    BOOL canSaveNewItem = [[self managedObjectContext] save:&error]; 
    if (!canSaveNewItem) 
    { 
    [NSApp presentError:error]; 
    } 

    [self clearFormFields]; // Private method that clears text fields, disables buttons 
    [NSApp endSheet:[self window] returnCode:NSOKButton]; 
} 

Я пытаюсь написать два метода испытания, чтобы проверить это: тот, который тестирует сценарий, когда управляемый объект не может спасти и один, где он успешно экономит.

@interface SGAddItemWindowControllerTests : SGTestCase 
{ 
@private 
    SGAddItemWindowController *addItemWindowController; 
    id mockApp; 
    id mockNameField; 
} 

- (void)setUp 
{ 
    mockNameField = [OCMockObject mockForClass:[NSTextField class]]; 
    mockApp = [OCMockObject mockForClass:[NSApplication class]]; 

    addItemWindowController = [[BLAddItemWindowController alloc] init]; 
    [addItemWindowController setValue:mockNameField forKey:@"itemNameTextField"]; 
} 

- (void)testAddingNewItemFromSheetFailed 
{ 
    // Setup 
    NSString *fakeName = @""; 
    [[[mockNameField expect] andReturn:fakeName] stringValue]; 
    [[mockApp expect] presentError:[OCMArg any]]; 

    // Execute 
    [addItemWindowController add:nil]; 

    // Verify 
    [mockApp verify]; 
} 

- (void)testAddingNewItemFromSheetSucceeds 
{ 
    // Setup 
    NSString *fakeName = @"Item Name"; 
    [[[mockNameField expect] andReturn:fakeName] stringValue]; 
    [[mockApp expect] endSheet:[OCMArg any] returnCode:NSOKButton]; 

    // Execute 
    [addItemWindowController add:nil]; 

    // Verify 
    [mockApp verify]; 
    [mockNameField verify]; 
} 

@end 

Вот вопросы, которые я знаю, у меня есть, но я не уверен, как работать:

  1. Я не уверен, как обращаться дело с контекстом управляемого объекта с точки зрения испытания. Должен ли я открыть весь основной стек данных или просто создать макет NSManagedObjectContext?
  2. Идея просто установить значения текстового поля как способ запуска выражения if выглядит неправильно. В идеале я думаю, что я должен заглушить метод save: и вернуть ДА или НЕТ, но с учетом вопроса 1 Я не уверен в аспектах основных данных.

Я думаю, что я на правильном пути, но я мог бы использовать второе мнение о том, как решить мои проблемы и поставить меня на правильный путь для тестирования фрагмента кода.

ответ

2

Джастин,

Что я могу сделать для вопроса # 1, чтобы создать реальную NSManagedObjectContext но создать им-памяти сохраняемости магазин. Ничто не попадает на диск, и я тестирую версию истины CoreData.

У меня есть класс MWCoreDataTest (проходит в моем случае GTMTestCase), который строит МПЦ и инициализирует постоянного хранилища

- (NSManagedObjectContext *) managedObjectContext { 

    if (managedObjectContext != nil) { 
     return managedObjectContext; 
    } 

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
    if (coordinator != nil) { 
     managedObjectContext = [[NSManagedObjectContext alloc] init]; 
     [managedObjectContext setPersistentStoreCoordinator: coordinator]; 
    } 

    return managedObjectContext; 
} 



- (NSPersistentStoreCoordinator*)persistentStoreCoordinator; 
{ 
    if (persistentStoreCoordinator) return persistentStoreCoordinator; 
    NSError* error = nil; 
    NSManagedObjectModel *mom = [self managedObjectModel]; 
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] 
            initWithManagedObjectModel:mom]; 


    if (![persistentStoreCoordinator addPersistentStoreWithType:NSInMemoryStoreType 
                configuration:nil 
                  URL:nil 
                 options:nil 
                  error:&error]) { 
     [[NSApplication sharedApplication] presentError:error]; 
     return nil; 
    } 
    return persistentStoreCoordinator; 
} 

WRT # 2, я думаю, что это нормально - если вы планируете на тестирование более одного поведения в классе, переместите

[addItemWindowController setValue:mockNameField forKey:@"itemNameTextField"]; 

к testAdding .. метод

Если вы решите # 1, то вы можете просто установить поле itemNameText до нуля и ваш сохранить проверка будет инициирована.

WRT # 3, я бы утверждать, что построение издеваться на NSApp === строит макет на NSApplication

0

Что такое, что вы хотите проверить? Вы хотите проверить, что Core Data делает сохранение или нет? Или вы хотите проверить, что ваше приложение правильно ответило на результат вызова CoreData?

В любом случае я думаю, вы должны извлечь метод, который выполняет сохранение вдоль линий:

-(BOOL)saveNewItem:(NSString *)itemName error:(NSError **)error { 
    SGItem *newItem = [NSEntityDescription insertNewObjectForEntityForName:kItemEntityName inManagedObjectContext:[self managedObjectContext]]; 
    newItem.name = itemName; 

    NSError *error = nil; 
    return[[self managedObjectContext] save:&error]; 
} 

- (IBAction)add:(id)sender { 
    NSString *itemName = [self.itemNameTextField stringValue]; 
    NSError *error = nil; 
    BOOL canSaveNewItem = [self saveNewItem:itemName error:&error]; 
    if (!canSaveNewItem) { 
    [NSApp presentError:error]; 
    } 

    [self clearFormFields]; // Private method that clears text fields, disables buttons 
    [NSApp endSheet:[self window] returnCode:NSOKButton]; 
} 

Таким образом, вы можете проверить, что сохранение основных данных работ, как ожидается настройки вверх по в магазине памяти и не должны заботиться о бизнес-логике. Вы также можете переопределить или высмеять результат этого метода для проверки бизнес-логики.

Я бы, возможно, даже переместил все материалы Core Data в отдельный класс, который бы инкапсулировал взаимодействие для более простого издевательства.

Смежные вопросы