나는 데이터 소스를 위임하고 분리 한 UITableView
을 가지고 있습니다. DataSource는 NSObject
- ArrayDataSource
클래스의 하위 클래스입니다.블록이이 클래스에서 호출 된 경우 어떻게 테스트해야합니까?
#import <Foundation/Foundation.h>
typedef void (^ConfigureCellBlock)(id cell, id object);
@interface ArrayDataSource : NSObject <UITableViewDataSource>
@property (nonatomic, readonly) NSArray *items;
@property (nonatomic, readonly) NSString *cellIdentifier;
- initWithItems:(NSArray *)items cellIdentifier:(NSString *)cellIdentifier configureCellBlock:(ConfigureCellBlock)block;
- (void)setItems:(NSArray *)items;
- (void)setCellIdentifier:(NSString *)cellIdentifier;
- (void)setConfigureCellBlock:(ConfigureCellBlock)block;
@end
#import "ArrayDataSource.h"
@interface ArrayDataSource()
@property (nonatomic, copy) ConfigureCellBlock configureCellBlock;
@end
@implementation ArrayDataSource {
NSArray *_items;
NSString *_cellIdentifier;
}
#pragma mark - External
- (id)initWithItems:(NSArray *)items cellIdentifier:(NSString *)cellIdentifier configureCellBlock:(ConfigureCellBlock)block {
self = [super init];
if (self) {
_items = items;
_cellIdentifier = cellIdentifier;
_configureCellBlock = [block copy];
}
return self;
}
- (void)setItems:(NSArray *)items {
_items = items;
}
- (void)setCellIdentifier:(NSString *)cellIdentifier {
_cellIdentifier = cellIdentifier;
}
- (void)setConfigureCellBlock:(ConfigureCellBlock)block {
_configureCellBlock = block;
}
#pragma mark - Private
- (id)_itemAtIndexPath:(NSIndexPath *)indexPath {
return _items[indexPath.row];
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _items.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
id cell = [tableView dequeueReusableCellWithIdentifier:_cellIdentifier forIndexPath:indexPath];
id item = [self _itemAtIndexPath:indexPath];
_configureCellBlock(cell, item);
return cell;
}
#pragma mark - Accessors
- (NSArray *)items {
return _items;
}
- (NSString *)cellIdentifier {
return _cellIdentifier;
}
@end
는 지금은 ConfigureCellBlock
이 tableView:cellForRowAtIndexPath:
에 올바른 인수로 호출 된 경우 테스트 할.
내 테스트는 이제 다음과 같이 보이지만 전달 및 차단이 결국 호출되지 않기 때문에 올바르게 작동하지 않습니다. 내 테스트 클래스는 _tableView
에 대한 대리인입니다.
#pragma mark - UITableView tests + Delegate + DataSource
- (void)testDataSource {
UITableView *_tableView = [[UITableView alloc] init];
_tableView.delegate = self;
[dataSource setItems:@[@"A"]];
[dataSource setConfigureCellBlock:^(UITableViewCell *cell, NSString *object) {
XCTAssertEqualObjects(object, @"B", @"");
}];
id mockDataSource = [OCMockObject partialMockForObject:dataSource];
SEL selector = NSSelectorFromString(@"_itemAtIndexPath:");
[[[mockDataSource stub] andReturn:dataSource.items[0]] methodForSelector:selector];
_tableView.dataSource = mockDataSource;
UITableViewCell *cell = [[UITableViewCell alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
id mockTableView = [OCMockObject partialMockForObject:_tableView];
[[[mockTableView stub] andReturn:cell] dequeueReusableCellWithIdentifier:OCMOCK_ANY forIndexPath:indexPath];
[mockTableView reloadData];
}
어떻게 올바르게 테스트해야합니까?
미리 감사드립니다.
거의 확실하게 문제를 해결할 수는 없지만 블록 설정 도구가 블록을 복사하지 않아야합니다 (생성자에서와 같이)? – sammyd
@sammyd이 복사본은 속성이 copy이기 때문에 생성자에서 불필요합니다. 하지만 고마워. –
블록을 속성을 백업하는 ivar에 할당하기 때문에 생성자 *의'[copy]'가 * 필요합니다. 속성 선언의'(copy)'지시자는 합성 된 setter에만 적용된다. 그러나 코드에서 setter를 오버라이드하고 copy를 사용하지 않으므로'self.configureCellBlock = block; '을 사용했다하더라도 복사하지 않는다. – sammyd