2010-02-15 83 views
4

我只是在理解TDD和嘲笑的概念,並且正在就如何正確處理問題。我有一張表單,可以讓用戶創建一個新的核心數據對象並將其保存到數據存儲中。我不確定我是否正在採取最好的方法來測試它。使用OCMock和核心數據測試控制器方法

- (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語句的方式似乎是錯誤的想法。理想情況下,我認爲我應該將​​方法剔除並返回YES或NO,但給出問題1我不確定它的核心數據方面。

我認爲我在正確的軌道上,但是我可以對如何解決我的問題並將我設置在測試代碼段的正確路徑上使用第二種意見。

回答

2

賈斯汀,

我的問題#1做的是創建一個實際的NSManagedObjectContext但創建IM內存持久存儲。沒有任何事情會發生,我測試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]; 
} 

這樣,您就可以測試核心數據保存作品設置了一個存儲在內存中,並沒有如預期必須關心業務邏輯。您還應該能夠覆蓋或模擬此方法的結果以測試業務邏輯。

我甚至可能將所有的核心數據的東西移動到一個單獨的類,將封裝交互更容易嘲笑。