gpt4 book ai didi

ios - 如何对 AFNetworking 请求进行单元测试

转载 作者:技术小花猫 更新时间:2023-10-29 11:18:51 27 4
gpt4 key购买 nike

我正在使用 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 的。我不知道是不是因为它只是一个示例,但您应该改为注入(inject)它(请参见下面的示例)。

其次,您正在创建请求,然后是 AFHTTPRequestOperation,然后将其排入队列。这很好,但您可以使用 AFHTTPClient 方法 getPath:parameters:success:failure: 获得相同结果。

我没有使用建议的 HTTP stub 工具 (Nocilla) 的经验,但我看到它基于 NSURLProtocol。我知道有些人使用这种方法,但我更喜欢创建自己的 stub 响应对象并模拟 http 客户端,就像您在以下代码中看到的那样。

Retriever 是我们要测试的类,我们将在其中注入(inject) AFHTTPClient。请注意,我直接传递了用户和事件 ID,因为我想让事情变得简单且易于测试。然后在其他地方,您可以将帐户 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 版本已发布,因此如果它满足您的要求,请考虑使用它。

关于ios - 如何对 AFNetworking 请求进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19095322/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com