在 iOS 上实现 TTD 时,尽量不要依赖系统调用委托和数据源方法。
您应该直接从单元测试中调用这些方法。只需为您的测试配置正确的环境即可。
例如,当我为 UICollectionView 实现 TDD 时,我创建了两个单独的类,专门用于实现 UICollectionViewDataSource 和 UICollectionViewDelegate 协议,创建关注点分离,我可以将这些类分别单元测试到视图控制器本身,尽管我仍然需要初始化视图控制器来设置视图层次结构。
这是一个示例,当然省略了标题和其他次要代码。
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
}