ios - 如何在 UIViewController 中对 UICollectionView 进行单元测试

标签 ios objective-c unit-testing uiviewcontroller uicollectionview

我想对 UIViewController 中的 UICollectionView 进行单元测试(例如,我想测试 UICollectionView 是否具有我期望它在我的单元测试中具有的单元格数量)

我的单元测试基于以下博客(关于如何对 View Controller 进行单元测试): http://yetanotherdevelopersblog.blogspot.co.il/2012/03/how-to-test-storyboard-ios-view.html

在单元测试中,我能够获得指向我正在测试的 UIViewController 中的 UICollectionView 的指针。这是我测试的 setUp 方法中的代码:

storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
viewController = [self.storyboard instantiateViewControllerWithIdentifier:@"MainViewController"];
[viewController performSelectorOnMainThread:@selector(loadView) withObject:nil waitUntilDone:YES];
self.collectionView = viewController.collectionView

不幸的是,此 UICollectionView 中没有单元格(即 self.collectionView.visibleCells.count 等于 0,因此我无法访问单元格并测试数据是否符合我的预期), 虽然在调试时我可以看到我的应用程序将这些单元格添加到 Collection View 中。

我做错了什么? 有关如何在 UIViewController 中对 UICollectionView 进行单元测试的任何提示和技巧?

编辑: 在 Roshan 的帮助下,我现在可以缩小问题范围。我正在对具有 UICollectionView 的 UIViewController 进行单元测试。在我的单元测试中,我想测试 CollectionView 中单元格的值是否符合我的预期。但是,collectionView:cellForItemAtIndexPath: 没有在我的 ViewController 上调用,因此当它作为单元测试调用时我的单元格不存在。有什么想法吗?

最佳答案

在 iOS 上实现 TTD 时,尽量不要依赖系统调用委托(delegate)和数据源方法。

您应该直接从单元测试中调用这些方法。只需为您的测试配置正确的环境即可。

例如,当我为 UICollectionView 实现 TDD 时,我创建了两个单独的类来专门实现 UICollectionViewDataSource 和 UICollectionViewDelegate 协议(protocol),创建关注点分离,我可以分别对 View Controller 本身对这些类进行单元测试,尽管我仍然需要初始化 View Controller 以设置 View 层次结构。

这是一个示例,当然省略了 header 和其他次要代码。

UICollectionViewDataSource 示例

@implementation CellContentDataSource

@synthesize someModelObjectReference = __someModelObjectReference;

#pragma mark - UICollectionViewDataSource Protocol implementation

- (NSInteger) collectionView:(UICollectionView *)collectionView
  numberOfItemsInSection:(NSInteger)section
{
    return __someModelObjectReference ? 
         [[__someModelObjectReference modelObjects] count] : 0;
}

- (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView
               cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString * const kCellReuseIdentifer =   @"Cell";
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCellReuseIdentifer forIndexPath:indexPath];

    ModelObject *modelObject = [__someModelObjectReference modelObjects][[indexPath item]];

    /* Various setter methods on your cell with the model object */

    return cell;
}
@end

单元测试示例

- (void) testUICollectionViewDataSource
{
    UIStoryBoard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    MainViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:@"MainViewController"];
    [viewController view]; // Loads the view hierarchy

    // Using OCMock to mock the returning of the model objects from the model object reference.
    // The helper method referenced builds an array of test objects for the collection view to reference
    id modelObjectMock = [OCMockObject mockForClass:[SomeModelObjectReference class]];
    [[[modelObjectMock stub] andReturn:[self buildModelObjectsForTest]] modelObjects];

    CellContentDataSource *dataSource = [CellContentDataSource new];
    dataSource.someModelObjectReference = modelObjectMock;
    viewController.collectionView.dataSource = dataSource;

    // Here we call the data source method directly
    UICollectionViewCell *cell = [dataSource collectionView:viewController.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];

    XCTAssertNotNil(cell, @"Cell should not be nil");
    // Assert your cells contents here based on your test model objects
}

关于ios - 如何在 UIViewController 中对 UICollectionView 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19619068/

相关文章:

ios - 无法在 Xcode 8.0 beta 6 上启用钥匙串(keychain)共享

ios - iPhone 4 一个 iPhone 应用程序可以占用多少内存

iphone - iOS - 链接器错误,重复符号

android - 无法使用 Charles Web 代理和 android 连接到 SSL,但仅用于测试

php - Laravel 5.2 单元测试集标题不起作用

ios - 在 Backendless 中存储一些特殊字符

ios - UIAlertController 解雇他的 presentingViewController

objective-c - 如何更改自定义 NSTextfield 的绘制矩形内的文本颜色

iphone - 如何在 iPhone 应用程序中进行Omniture 追踪

python - 使用 catkin_make 测试触发 python rostest