Testing controller method with OCMock and Core Data

最后都变了- 提交于 2019-12-03 17:21:33

Justin,

What I do for question #1 is to create an actual NSManagedObjectContext but create an im-memory persistence store. Nothing hits the disk and I test the CoreData version of the truth.

I have a MWCoreDataTest class (extends in my case GTMTestCase) that builds the moc and initializes the persistence store

    - (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, I think that's ok - if you plan on testing more than one behavior in the class, move the

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

to the testAdding.. method

If you solve #1, then you could just set the itemNameText field to nil and your save validation would trigger.

WRT #3, I would validate that building a mock on NSApp === building a mock on NSApplication

What is that you want to test? Do you want to test that Core Data does the saving or not? Or, do you want to test that your application responds correctly to the result of the call to CoreData?

Either way I think you should extract a method that performs the saving along the lines of:

-(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];
}

This way you can test that Core Data saving works as expected by settings up an in memory store and not have to care about the business logic. You should also be able to override or mock the result of this method for testing the business logic.

I would perhaps even move all the Core Data stuff to a separate class that would encapsulate the interaction for easier mocking.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!