我正在尝试为我班级中的一个方法编写单元测试。该方法进行服务器调用并通过完成&错误块。我知道如何从测试类进行异步服务器调用,但我怀疑的是如何测试使服务器调用完成的方法&错误块。这里的目的是检查是否完成&错误块正确处理服务器响应。
如果有人在此之前做过这个,请指导。如果我的理解不正确,请纠正我。
以下是一种此类方法的示例。在这里,我想编写一个可以测试“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];
}
答案 0 :(得分: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);
中找到许多有关使代码可测试的有用信息