2013-04-21 10 views
2

NSFetchedResultsControllerDelegate protocol을 구현하는보기 컨트롤러에 대한 단위 테스트를 작성하려고합니다. 구현의 첫 번째 테스트 (이 뷰 컨트롤러의 다른 테스트 후)는 새 개체가 삽입 될 때 테이블 행이 테이블 뷰에 삽입되는지 확인하는 것입니다.단위 테스트 방법 NSFetchedResultsControllerDelegate?

시험의 내 첫 번째 구현했다 :

- (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]; 
} 
:

- (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)로 이동 뷰 컨트롤러의 기능을 구현했을 때, 나는 다음과 같은 코드를 작성

그러나, 나는 이렇게 되었 가져올 수 없습니다 및 오류는 다음과 같습니다

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]]; 

, 나는 현재 OCUnitOCMock을 사용하고 있습니다. 나는이 툴셋으로 이런 종류의 테스트를 만드는 것이 불가능한 경우에만 다른 툴을 고려할 것이며, 그럴 경우 그 툴셋의 한계에 대한 설명에 감사 할 것입니다.

내가 이해하는 한, 모의은 그렇게 할 때도 수업의 성격에 대해 "거짓말"할 수 없다. 또한 오류는 UITableView이 찾고있는 클래스에 대한 정보를 제공하지 않습니다. -isKindOfClass:을 테스트하는 것은 좋은 습관은 아니지만 제 코드가 아님을 압니다.

도움 주셔서 감사합니다.

+0

를 부를 것이다 'expect' 전에 그런 andReturn''와 함께 사용. 난 당신이 그것을 "스텁"해야한다고 생각 ... –

+0

@ David 나는 다른 테스트에서 성공적으로 사용하고 있습니다. 그것이 틀렸다고 확신합니까? –

+0

아니요, 확실하지 않습니다. 나는 전에 그것을 보지 못했지만 그것이 틀렸다는 것을 의미하지는 않습니다. –

답변

0

내부 동작을 숨기고있는 조롱하는 개체를 해결하기위한 한 가지 방법은 부분 모의를 사용하는 것입니다. 귀하의 경우 :이 작업을 수행 할 때

id tableViewMock = [OCMock partialMockForObject:[[UITableView alloc] init]]; 

내가 일반적으로 약간의 이름을 변경하고 나는 보지 못했다 tableViewPartial

+0

tableViewMock = [OCMock partialMockForObject : sut.tableView]를 사용할 수도 있습니다. –

0

이전에 isKindOfClass: 전화와 관련된 오류가 발생했으며, 이는 일반적으로 Apple이 자체 코드에서 특정 기능을 구현 한 결과입니다. mockForClass: 표준은 예상치 못한 메시지를 실패한 상황으로 간주합니다. 간단한 해결책은 예기치 못한 메시지를 용서하는 niceMockForClass:으로 모의을 전환하는 것입니다.

타사 코드에서 오는 메시지에 대한 기대치를 추가하면 테스트를 외부 구현 세부 정보와 매우 결합하게됩니다. isKindOfClass:이 호출되도록하는 것은 분명히 시스템의 명시적인 요구 사항이 아닙니다.

+0

감사합니다. 재미 있은만큼, 나는 좋은 mock을 사용한다. 테스트는 실패한다. 어떻게 든 tableView는 뷰 컨트롤러에서 아무 것도되지 않기 때문이다. –

+0

커플 링에 대한 의견에 대해서도 동의합니다. 나는 이것에 대해서도 걱정하고있다. 테스트를 구현하는 더 좋은 방법이 있습니까? –

+1

UITableView를 만들고 부분적으로 조롱하면 어떻게 될까요? –