我正在通过AFNetworking作为GET请求来检索
JSON数据,如下所示:
NSURL *url = [NSURL URLWithString:K_THINKERBELL_SERVER_URL];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
Account *ac = [[Account alloc]init];
NSMutableuRLRequest *request = [httpClient requestWithMethod:@"GET" path:[Nsstring stringWithFormat:@"/user/%@/event/%@",ac.uid,eventID] parameters:nil];
AFHTTPRequestOperation *operation = [httpClient HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation,id responSEObject) {
NSError *error = nil;
NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:responSEObject options:NSJSONReadingallowFragments error:&error];
if (error) {
}
[self.delegate NextMeetingFound:[[Meeting alloc]init] meetingData:JSON];
}
failure:^(AFHTTPRequestOperation *operation,NSError *error){
}];
[httpClient enqueueHTTPRequestOperation:operation];
事情是我想基于这个数据创建一个单元测试,但我不想让测试实际上会提出请求.我希望预定义的结构将作为响应返回.我是一个新的单元测试,并戳了一点Ocmock,但不知道如何管理这个.
解决方法
几个事情要评论你的问题.
首先,您的代码很难测试,因为它直接创建了AFHTTPClient.我不知道是不是因为它只是一个样本,但是你应该注入它(参见下面的示例).
首先,您的代码很难测试,因为它直接创建了AFHTTPClient.我不知道是不是因为它只是一个样本,但是你应该注入它(参见下面的示例).
其次,您正在创建请求,然后是AFHTTPRequestOperation,然后将其排入队列.这很好,但您可以使用AFHTTPClient方法getPath获取相同的参数:参数:success:failure:.
我没有那个建议的HTTP stubbing工具(Nocilla)的经验,但我看到它是基于NSURLProtocol.我知道有些人使用这种方法,但我更喜欢创建自己的stubbed响应对象,并模仿http客户端,就像在下面的代码中看到的那样.
Retriever是我们要测试我们注入AFHTTPClient的类别.
请注意,我直接传递用户和事件ID,因为我想保持简单易用的测试.然后在其他地方你可以将accout uid值传递给这个方法等等…
头文件看起来与此类似:
#import <Foundation/Foundation.h> @class AFHTTPClient; @protocol RetrieverDelegate; @interface Retriever : NSObject - (id)initWithHTTPClient:(AFHTTPClient *)httpClient; @property (readonly,strong,nonatomic) AFHTTPClient *httpClient; @property (weak,nonatomic) id<RetrieverDelegate> delegate; - (void) retrieveEventWithUserId:(Nsstring *)userId eventId:(Nsstring *)eventId; @end @protocol RetrieverDelegate <NSObject> - (void) retriever:(Retriever *)retriever didFindEvendata:(NSDictionary *)eventData; @end
执行文件:
#import "Retriever.h"
#import <AFNetworking/AFNetworking.h>
@implementation Retriever
- (id)initWithHTTPClient:(AFHTTPClient *)httpClient
{
NSParameterassert(httpClient != nil);
self = [super init];
if (self)
{
_httpClient = httpClient;
}
return self;
}
- (void)retrieveEventWithUserId:(Nsstring *)userId eventId:(Nsstring *)eventId
{
Nsstring *path = [Nsstring stringWithFormat:@"/user/%@/event/%@",userId,eventId];
[_httpClient getPath:path
parameters:nil
success:^(AFHTTPRequestOperation *operation,id responSEObject)
{
NSDictionary *eventData = [NSJSONSerialization JSONObjectWithData:responSEObject options:0 error:NULL];
if (eventData != nil)
{
[self.delegate retriever:self didFindEventData:eventData];
}
}
failure:nil];
}
@end
和测试:
#import <XCTest/XCTest.h>
#import "Retriever.h"
// Collaborators
#import <AFNetworking/AFNetworking.h>
// Test support
#import <Ocmock/Ocmock.h>
@interface RetrieverTests : XCTestCase
@end
@implementation RetrieverTests
- (void)setUp
{
[super setUp];
// Put setup code here; it will be run once,before the first test case.
}
- (void)tearDown
{
// Put teardown code here; it will be run once,after the last test case.
[super tearDown];
}
- (void) test__retrieveEventWithUserIdEventId__when_the_request_and_the_JSON_parsing_succeed__it_calls_didFindEventData
{
// Creating the mocks and the retriever can be placed in the setUp method.
id mockHTTPClient = [OcmockObject mockForClass:[AFHTTPClient class]];
Retriever *retriever = [[Retriever alloc] initWithHTTPClient:mockHTTPClient];
id mockDelegate = [OcmockObject mockForProtocol:@protocol(RetrieverDelegate)];
retriever.delegate = mockDelegate;
[[mockHTTPClient expect] getPath:@"/user/testUserId/event/testEventId"
parameters:nil
success:[OCMArg checkWithBlock:^BOOL(void (^successBlock)(AFHTTPRequestOperation *,id))
{
// Here we capture the success block and execute it with a stubbed response.
Nsstring *jsonString = @"{\"some valid JSON\": \"some value\"}";
NSData *responSEObject = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
[[mockDelegate expect] retriever:retriever didFindEventData:@{@"some valid JSON": @"some value"}];
successBlock(nil,responSEObject);
[mockDelegate verify];
return YES;
}]
failure:Ocmock_ANY];
// Method to test
[retriever retrieveEventWithUserId:@"testUserId" eventId:@"testEventId"];
[mockHTTPClient verify];
}
@end
最后要注意的是,AFNetworking 2.0版本被发布,所以考虑使用它,如果它涵盖了您的要求.