2013-09-29 6 views
0

UITableViewCells를 모방하고 테스트하여 configureCell : forIndexPath가 올바르게 작동하는지 확인하려고합니다. isKindOfClass를 사용하여 작동하도록 설정할 수는 있지만 conformsToProtocol 만 사용할 수 있습니다. 이것은 모든 나의 uitableviewcells가 자신의 프로토콜을 가지고 필요로하지 않는 것입니다.UITableViewCell을 조롱하고 isKindOfClass를 사용합니다.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    FeedObj *item = [_feedElements objectAtIndex:indexPath.row]; 
    if(item.obj_type == FeedObjTypeFriendAdd) { 
    MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyTableViewCellIdentifier forIndexPath:indexPath]; 
    [self configureCell:cell forIndexPath:indexPath] 
    return cell; 
    } else if(item.obj_type = FeedObjTypeSomeOtherType) { 
    // do another cell 
    } 
} 

- (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath 
{ 
    // only enters conditional in test if I do [cell conformsToProtocol:@protocol(SomeIndividualProtocolForEachTableViewcell)]     
    if([cell isKindOfClass:[MyTableViewCell class]]) { 
    // do the configuring 
    FeedObj *item = [_streamElements objectAtIndex:indexPath.row]; 

    NSString *firstName = [item.obj_data objectForKey:@"first_name"]; 
    NSString *lastName = [item.obj_data objectForKey:@"last_name"]; 
    NSString *name = [NSString stringWithFormat:@"%@ %@.", firstName, [lastName substringToIndex:1]]; 
    NSString *text = [NSString stringWithFormat:@"%@ has joined", name]; 

    [((MyTableViewCell *)cell).messageLabel setText:text]; 

    } else if([cell isKindOfClass[SomeOtherTableView class]]) { 
    // do other config 
    } 
} 


    @implementation SampleTests 
    - (void)setUp 
    { 
     _controller = [[MySampleViewController alloc] init]; 
     _tableViewMock = [OCMockObject niceMockForClass:[UITableView class]]; 
     [_tableViewMock registerNib:[UINib nibWithNibName:@"MyTableViewCell" bundle:nil] forCellReuseIdentifier:MyTableViewCellIdentifier]; 
    } 

    - (void)testFriendAddCell 
    { 
     FeedObj *friendAdd = [[FeedObj alloc] init]; 
     friendAdd.obj_type = FeedObjTypeFriendAdd; 
     friendAdd.obj_data = [NSMutableDictionary dictionaryWithDictionary:@{ @"first_name" : @"firstname", @"last_name" : @"lastname" }]; 
     _mockStreamElements = [NSMutableArray arrayWithObject:friendAdd]; 
     [_controller setValue:_mockStreamElements forKey:@"_feedElements"]; 

     NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; 
     [[[_tableViewMock expect] andReturn:[[[NSBundle mainBundle] loadNibNamed:@"MyTableViewCell" owner:self options:nil] lastObject]] dequeueReusableCellWithIdentifier:MyTableViewCellIdentifier forIndexPath:indexPath]; 

     MyTableViewCell *cell = (MyTableViewCell *)[_controller tableView:_tableViewMock cellForRowAtIndexPath:indexPath]; 
     STAssertNotNil(cell, @"should not be nil"); 
     STAssertTrue([cell.messageLabel.text isEqualToString:@"firstname l. has joined"], @"should be equal"); 
     [_tableViewMock verify]; 
    } 
    @end 

은 또한 일을 해봤 [[[mockCell 스텁] andReturnValue : OCMOCK_VALUE ((BOOL) {예})] isKindOfClass : [MyTableViewCell 클래스]]는 mockCell와] 기대와 그 중 하나가 작동하지 않습니다 . 이렇게 :

id mockCell = [OCMockObject partialMockForObject:[[[NSBundle mainBundle] loadNibNamed:@"MyTableViewCell" owner:self options:nil] lastObject]]; 
[[[mockCell stub] andReturnValue:OCMOCK_VALUE((BOOL) {YES})] isKindOfClass:[OCMConstraint isKindOfClass:[MyTableViewCell class]]]; 
[[[_tableViewMock expect] andReturn:mockCell] dequeueReusableCellWithIdentifier:MyTableViewCellIdentifier forIndexPath:indexPath]; 

심지어 http://blog.carbonfive.com/2009/02/17/custom-constraints-for-ocmock/에 나열된 OCMConstraint로 시도했습니다.

어쨌든이 작업을 수행 할 또는 각 tableviewcell에 대한 프로토콜을 사용해야합니까? 미리 감사드립니다.

+1

configureCell 메서드 정의 란 무엇입니까? 그것이 전달 된 셀에 대해 MyTableViewCell *을 사용합니까? –

+0

MyTableViewCell은 확실히 UITableViewCell의 하위 클래스입니까? –

+0

configureCell 메서드 정의를 추가했으며 예 MyTableViewCell은 확실히 UITableViewCell의 하위 클래스입니다. xib을 사용하고 있으며 UITableViewCell을 확장하고 xib의 클래스 이름을 MyTableViewCell로 설정합니다. – user2828419

답변

1

이 구현을 어떻게 구현하는지 다시 생각해 보시기 바랍니다. 처음에는 뷰 컨트롤러가 뷰 관리에 적합하지만 모델 데이터를 관리하는 것이 목적이 아닙니다. 모델 데이터를 관리하는 뷰로 전달할 때 유용하기 때문에이를 염두에두고 이와 같이 빌드 해 봅시다.

FeedController이라는 새 클래스를 소개해 드리겠습니다. 이 컨트롤러의 역할은이 화면을 지원하는 VC와 모델 데이터 사이에 앉아서 작업하는 것입니다. 이 공개 인터페이스를 다음과 같이 가정 해 보겠습니다.이 메소드를 구현하지는 않겠지 만 예상했던 것과 똑같을 것입니다. 이니셜 라이저는 전달 된 배열을 복사하여 ivar에 저장하고 다른 메서드는 특정 인덱스의 배열에서 정보를 가져 와서 사용자 정의 변환을 적용합니다 (이름과 성을 결합하여 전체 이름을 얻으십시오). 여기서의 주요 목표는 데이터를 조작하는 것이 아니라 데이터를 전송하는 것입니다. 보기 컨트롤러에서이 데이터를 조작하고 조작하는 순간, 정사각형으로 다시 돌아가는 것이 현명합니다.

configureCell:forIndexPath:의 객체는 지금 테스트하기가 무한히 쉬운 FeedController 클래스의 데이터를 전송하기위한 것입니다. 응답 체인을 설정하거나, 객체를 조롱하거나, 아무 것도 필요가 없습니다. 일부 조명기 데이터를 제공하면됩니다.

configureCell:forIndexPath:을 구성하는 조각을 테스트하고 있지만 더 이상 직접 테스트 할 수는 없습니다. 보기에 올바르게 채워지는지 확인하려면 꼭 그래야합니다. 그러나 이것을 다르게 할 것입니다. 이것은 단위 테스트의 일이 아닙니다. UIAutomation 또는 좋아하는 UI 테스트 프레임 워크를 추출하고 UI를 테스트하십시오. FeedController의 단위 테스트를 사용하여 데이터 및 변형을 테스트하십시오.

이 정보가 도움이되기를 바랍니다.

+0

나는 이것을 시험해 볼 것입니다! – user2828419

+1

이 패턴이 제대로 작동하므로 올바른 답으로 표시하고 있습니다. 고맙습니다! – user2828419