[英]How do I unit test NSFetchedResultsControllerDelegate (controllerWillChangeContent and controllerDidChangeContent) using Swift
[英]How to unit test NSFetchedResultsControllerDelegate?
我正在尝试为实现NSFetchedResultsControllerDelegate协议的视图控制器编写单元测试。 实现的第一个测试(此视图控制器的其他测试之后)是在插入新对象时验证表行是否已插入到表视图中。
我对该测试的第一个实现是:
- (void) setUp {
[super setUp];
sut = [[JODataTableViewController alloc] init];
fetchedResultsCtrlrMock = [OCMockObject niceMockForClass:[NSFetchedResultsController class]];
NSError *__autoreleasing *err = (NSError *__autoreleasing *) [OCMArg anyPointer];
[[[fetchedResultsCtrlrMock expect] andReturnValue:OCMOCK_VALUE((BOOL){YES})] performFetch:err];
[sut setValue:fetchedResultsCtrlrMock forKey:@"fetchedResultsController"];
[sut view]; // This invokes viewDidLoad.
}
- (void) tearDown {
sut = nil;
[super tearDown];
}
- (void) testObjectInsertedInResultsAddsARowToTheTable {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
id tableViewMock = [OCMockObject mockForClass:[UITableView class]];
sut.tableView = tableViewMock;
[[tableViewMock expect] insertRowsAtIndexPaths:@[indexPath]
withRowAnimation:UITableViewRowAnimationLeft];
[sut controller:nil didChangeObject:nil
atIndexPath:nil
forChangeType:NSFetchedResultsChangeInsert
newIndexPath:indexPath];
[tableViewMock verify];
}
当它尝试在视图控制器中实现将功能转换为绿色状态(TDD)时,我编写了以下代码:
- (void) controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
- (void) controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
UITableViewCell *cell;
switch (type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertRowsAtIndexPaths:@[newIndexPath]
withRowAnimation:UITableViewRowAnimationLeft];
break;
}
}
- (void) controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
但是,我无法通过它,错误是:
Test Case '-[JODataTableViewControllerTests testObjectInsertedInResultsAddsARowToTheTable]' started.
Unknown.m:0: error: -[JODataTableViewControllerTests testObjectInsertedInResultsAddsARowToTheTable] : OCMockObject[UITableView]: unexpected method invoked: isKindOfClass:<??>
Test Case '-[JODataTableViewControllerTests testObjectInsertedInResultsAddsARowToTheTable]' failed (0.001 seconds).
我尝试将以下行添加一次或多次到测试的准备部分,结果相同。
[[[tableViewMock expect] andReturnValue:OCMOCK_VALUE((BOOL){YES})] isKindOfClass:[OCMArg any]];
如您所见,我目前正在使用OCUnit
和OCMock
。 仅当无法使用此工具集创建此类测试时,我才会考虑使用其他工具,在这种情况下,如果它们存在,我希望对它们的局限性做出解释。
据我了解,即使被告知,该模拟也无法“撒谎”其类的性质。 同样,该错误不提供有关UITableView
正在查找的类的信息。 我知道使用-isKindOfClass:
并不是测试的好习惯,但这不是我的代码。
谢谢您的帮助。
我曾经见过与isKindOfClass:
调用相关的失败,它们通常是Apple在自己的代码中实现特定功能的方式的结果。 标准的mockForClass:
将拒绝任何意外消息,作为失败情况。 一个简单的解决方案是将您的模拟切换到niceMockForClass:
这niceMockForClass:
此类意外消息。
增加对来自第三方代码的消息的期望,将使您的测试与外部实现细节紧密结合。 确保isKindOfClass:
被调用显然不是系统的明确要求。
解决具有隐藏内部行为的模拟对象的一种方法是使用部分模拟。 在您的情况下:
id tableViewMock = [OCMock partialMockForObject:[[UITableView alloc] init]];
当我这样做时,我通常会稍微更改名称,并将其命名为tableViewPartial
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.