2015-08-24 42 views
0

我正在嘗試爲我的課程中的某個方法編寫單元測試。此方法發起服務器調用並通過完成&錯誤塊。我知道如何從測試類中進行異步服務器調用,但我懷疑如何測試使服務器調用完成&錯誤塊的方法。這裏的意圖是檢查完成&錯誤塊是否正確處理服務器響應。服務器調用完成和錯誤塊的單元測試

如果有人已經這樣做過,那麼請指導。如果我的理解不正確,請糾正我。

下面是一個這樣的方法的例子。在這裏,我想寫一個單元測試,它可以測試'fetchItems'方法的成功和錯誤處理情況。

- (void)fetchItems { 
    __weak MyListController *aBlockSelf = self; 
    NSDictionary *aPostBody = @{kMyCategoryId : self.categoryId}; 

    // Fetch Items List From Server 
    self.requestHandler = [[MyRequestHandler alloc] initWithEndPoint:[kMyFetchQuickListCategoryProductsURLKey MyEndPoint] body:aPostBody container:self.view loadingOverlayTitle:nil successHandler:^(NSDictionary *iResponse) { 
     if (iResponse) { 
      aBlockSelf.isInfoData = [iResponse boolForKey:@"infoData"]; 
      aBlockSelf.isTestEnabled = [iResponse boolForKey:@"enabled"]; 
      NSArray *categoryData = iResponse[@"categoryData"]; 
      NSArray *itemList = categoryData[0][@"items"]; 

      NSSortDescriptor *aSortDescriptor = [[NSSortDescriptor alloc] initWithKey:kMySortOrderKey ascending:YES]; 
      aBlockSelf.itemList = [MyListData quickListDataArray:[NSMutableArray arrayWithArray:[itemList sortedArrayUsingDescriptors:@[aSortDescriptor]]] withInventory:@10 andISInfoData: aBlockSelf.isInfoData]; 
     } 

     [aBlockSelf fetchImages]; 
     [aBlockSelf refresh]; 
    } andErrorHandler:^(NSString *iMessage, NSString *iKey, NSInteger iErrorCode, BOOL iIsNetworkError) { 
     MySessionObject.selectedCategory = nil; 

     ([aBlockSelf.alertView isVisible]) { 
      [aBlockSelf.alertView dismissWithClickedButtonIndex:self.alertView.cancelButtonIndex animated:YES]; 
     } 

     aBlockSelf.alertView = nil; 

     if (iIsNetworkError) { 
      aBlockSelf.alertView = [[MyUIAlertView alloc] initWithTitle:@"Error" message:iMessage cancelButtonTitle:@"OK" cancelButtonActionHandler:^{ 
       [aBlockSelf dismissViewController]; 
      } otherButtonTitle:nil andOtherButtonActionHandler:nil]; 

      [aBlockSelf.alertView show]; 
     } 

     aBlockSelf.navigationItem.rightBarButtonItem.enabled = YES; 
     aBlockSelf.navigationItem.leftBarButtonItem.enabled = YES; 
    }]; 

    [self.requestHandler executeRequest]; 
} 
+1

一些示例代碼將是有益的許多有用的信息。 –

+0

@TomaszBąk:謝謝你的回覆。我仍然懷疑確切的實施。我已經添加了一個示例方法,我正在嘗試編寫一個測試用例。你能否參考這個方法來解釋一下。 – Abhinav

回答

0

通常,如果您的服務器請求與您的模型混合在一起,則應該使用新對象或抽象接口將它分開。感謝這一點,在測試時,您可以存儲您的服務器以發送固定的響應。比方說,你已經分居發送請求到該對象:

@interface ServerCommuncation : NSObject 

- (void)request:(id)request completion:(void (^)(NSError *error))completion; 

@end 

現在,在你的單元測試,你可以注入存根:

@interface ServerCommuncationStub : ServerCommunication 

@property (nonatomic, copy) void (^completion)(NSError *error); 

@end 

@implementation ServerCommuncationStub 

- (void)request:(id)request completion:(void (^)(NSError *error))completion { 
    self.completion = completion; 
} 

,並調用完成時,它適合你:

ServerCommuncationStub *stub = [ServerCommuncationStub new]; 
Model *model = [[Model alloc] initWithServerCommunication:stub]; 
[model request]; 
stub.completion(nil); 

更好的方法是使用嘲諷庫。我個人使用OCMockito。你可以有同樣的效果沒有子:

ServerCommuncation *mock = mock([ServerCommuncation class]); 
Model *model = [[Model alloc] initWithServerCommunication:mock]; 
[model request]; 

MKTArgumentCaptor *captor = [MKTArgumentCaptor new]; 
[verify(mock) request:anyting() completion:[captor capture]]; 
void(^block)(NSError *error) = [captor value]; 
block(nil); 

您可以找到有關使您的代碼可測試在RefactoringWorking Effectively with Legacy Code