2013-07-13 3 views
0

"if 조건"이 너무 많고 contions에서 배열 개수를 확인하는 복잡한 방법에 대해 OCMock을 사용하여 단위 테스트를 작성하는 방법.OCMock을 이용한 복잡한 방법에 대한 단위 테스트

- (BOOL)someMethod 
{ 
    BOOL bUploadingLocation = false; 
    CLLocation *newLocation = nil; 

    if([locationCallbacks count] > 0) 
    { 
     for(CLLocation* receivedlocation in locationCallbacks) { 
      //Print 
     } 
     newLocation = [locationCallbacks objectAtIndex:[locationCallbacks count] - 1]; 
    } 
    else 
    { 
     return bUploadingLocation; 
    } 

    BOOL initialLocation = false; 
    CLLocation *lastKnownLocation = [[ASAppProfileService sharedInstance] getStoredLastKnownLocation]; 
    if(lastKnownLocation == nil) 
    { 
     initialLocation = true; 
    } 

    BOOL checkedInstatusChange = false; 
    if([[CRMgr getSharedInstance] isCREnabled]) 
    { 
     checkedInstatusChange = [[CRMgr getSharedInstance] orchestrateCROperationsWithLocation:newLocation]; 
    } 

    BOOL lastGoodUploadIsWithinThresold = [MELocationUtils isLastAccurateUploadWithinThresold]; 

    if(initialLocation || checkedInstatusChange || !lastGoodUploadIsWithinThresold) 
    { 
     BOOL bCanUpload = [[ASAppProfileService sharedInstance] canUploadData]; 
     if(bCanUpload) 
     { 
      [[MEProtocolHelper sharedDataUploadManager] uploadLocationInformationPayload:newLocation]; 
      bUploadingLocation = true; 
     } 
     else 
     { 
      //Print something 
     } 
    } 

    return bUploadingLocation; 
} 

어떻게 방법의 이러한 종류의 단위 테스트를 작성하기 : 여기 내 샘플 방법?

답변

2

@Ben_Flynn의 답변에 추가하기 위해 클래스를 디자인하는 방법은 mock을 사용하여 테스트하는 것이 얼마나 쉬운 지에 영향을줍니다. 귀하의 예에서, 당신은 당신을 상대로 일할 몇 가지 디자인 결정을 내 렸습니다. 이들은 다음을 포함한다 : 클래스 메소드가 아닌 인스턴스 메소드에 의존 싱글에 (. 예 [ASAppProfileService sharedInstance])

  • 을 많은 직접 참조를 사용

    • . (예 : [MELocationUtils isLastAccurateUploadWithinThresold])

    싱글 톤 및 클래스 메서드는 조롱하기가 악명 높습니다. Objective-C의 더 모호한 언어 기능에 대해 잘 알고 있다면 할 수 있습니다.하지만 일반적으로 클래스를 다시 디자인하여 테스트하기 쉽도록하는 것이 좋습니다.

    싱글 톤을 사용할 때 테스트 중에 테스트 중에 모의 코드로 싱글 톤을 바꾸기 위해 클래스에서 사용할 속성 (@property)을 정의하십시오. 가이를 구현하는 방법에는 여러 가지가 있지만, 여기에 내가 자주 사용하는 한 가지 방법 ... 헤더 파일에서

    입니다 (예 :가. "MyThing.h") 구현 파일에서

    @interface MyThing : NSObject 
    
    @property (strong, nonatomic) ASAppProfileService *profileService; 
    
    @end 
    

    (전 "MyThing.m") 당신의 단위 테스트에서

    @implementation MyThing 
    
    - (id)init 
    { 
        if (self = [super init]) { 
         // Initialize with singleton by default. 
         _profileService = [ASAppProfileService sharedInstance]; 
        } 
        return self; 
    } 
    
    - (BOOL)someMethod 
    { 
        CLLocation *lastKnownLocation = [self.profileService getStoredLastKnownLocation]; 
        … 
    } 
    
    @end 
    

    :.

    - (void)test_someMethod 
    { 
        id mockProfileService = [OCMockObject mockForClass:[ASAppProfileService class]]; 
    
        /* 
        TODO: Use [mockProfileService stub] to stub a return value 
        for the getStoredLastKnownLocation method. 
        */ 
    
        MyThing *thing = [[MyThing alloc] init]; 
    
        // Replace the default value of profileService with our new mock. 
        thing.pofileService = mockProfileService; 
    
        // Exercise your object under test. 
        BOOL result = [thing someMethod]; 
    
        /*TODO: Add your assertions here. */ 
    } 
    

    위의 그림은 의존성 삽입이라는 디자인 패턴입니다. 나는 그 디자인 패턴을 읽어 보길 권한다.쉽게 테스트 할 수있는 코드를 작성하는 데 엄청난 도움이되며 클래스 간의 커플 링을 줄여서 코드를 변경하기 쉽고 버그에 대한 내성을 높일 수 있습니다.

  • 2

    참고로이 메서드의 출력을 제어하는 ​​조건은 다양합니다. 몇 가지 테스트를 작성해야합니다 (조건 당 하나의 테스트를 작성합니다). 시험 당에서 그들을 설정에서, 각각의 시험에 편리 할 것

    ASAppProfileService 
    CRMgr 
    MELocationUtils 
    MEProtocolHelper 
    

    이 망신 시켰습니다 그래서 아무 의미 : 나는 당신에게 전화하는 모든 서비스에 대한 모의 객체를 만들 수 없을 것입니다 내 setup 방법에서

    기초. 또한 인스턴스 또는 클래스 방법에서 이러한 서비스를 포장 고려할 수

    호출 : 쉽게 조롱 만들 수있는 것입니다

    + (BOOL)isCheckedInStatusChange 
    { 
        BOOL checkedInStatusChange = NO; 
        if([[CRMgr getSharedInstance] isCREnabled]) 
        { 
         checkedInStatusChange = [[CRMgr getSharedInstance] orchestrateCROperationsWithLocation:newLocation]; 
        } 
        return checkedInStatusChange; 
    } 
    

    .

    그러나 궁극적으로 각 가능한 입력 세트를 테스트하고 출력을 검증하는 지름길은 없습니다.

    관련 문제