AFNetworking 单元测试
Posted
技术标签:
【中文标题】AFNetworking 单元测试【英文标题】:AFNetworking Unit Tests 【发布时间】:2014-08-15 17:40:47 【问题描述】:我正在尝试使用以下代码进行单元测试。但是,测试只是挂在等待部分。我的测试代码如下。我是 ios 和 AFNetworking 的新手。任何帮助将不胜感激。
我知道的事情: 正在调用 USAPIConnection 中的方法。 在 TestController 上没有调用成功或失败方法。 对 rails api 的请求正在运行。 (我知道它会返回 200 OK 代码)。
我不知道的事情: AFHTTPRequestOperationManager 实际上是在发送请求吗? 为什么没有成功发送失败方法? 这个单元测试是否足以进行测试?
XC测试代码
#import <XCTest/XCTest.h>
#import "USAPIConnection.h"
#import "Controller.h"
@interface TestController : NSObject <Controller>
@property bool done;
@end
@implementation TestController
-(void)asynchronousSuccessfulWithObject:(id)object type:(int)type
NSLog(@"Object: %@", object);
XCTAssertNotNil(object,"@Should have returned JSON object: %s",__PRETTY_FUNCTION__);
_done = true;
-(void)asynchronousUnsuccessfulWithError:(NSError *)error type:(int)type
XCTFail(@"Unsuccessful async call with error%s: %s",error,__PRETTY_FUNCTION__);
_done = true;
@end
@interface USAPIConnectionTests : XCTestCase
@end
@implementation USAPIConnectionTests
- (void)setUp
[super setUp];
NSLog(@"Beginning Test: %s",__PRETTY_FUNCTION__);
- (void)tearDown
NSLog(@"Ending Test: %s",__PRETTY_FUNCTION__);
[super tearDown];
- (void)testGetTeamById
TestController* testController = [[TestController alloc] init];
testController.done = false;
[USAPIConnection getTeamById:1 controller:testController];
int count = 0;
while(!testController.done && count < 10)
//Waiting
[NSThread sleepForTimeInterval:3.0];
count = count + 1;
if(count == 10)
XCTFail(@"Timed out: %s",__PRETTY_FUNCTION__);
@end
USAPIConnection 中调用的方法
+(void)getTeamById:(int)identity controller:(id<Controller>)controller
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFJSONResponseSerializer* serializer = [AFJSONResponseSerializer serializer];
serializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];
manager.responseSerializer = serializer;
[manager POST:[NSString stringWithFormat:@"http://%@/team/%D",baseURL,identity] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject)
[controller asynchronousSuccessfulWithObject:responseObject type:TYPETEAMSBYNAME];
failure:^(AFHTTPRequestOperation *operation, NSError *error)
[controller asynchronousUnsuccessfulWithError:error type:TYPETEAMSBYNAME];
];
尝试
尝试将测试方法更改为以下。但是,测试控制器中的 NSLog 都没有运行。
- (void)testGetTeamById
TestController* testController = [[TestController alloc] init];
testController.done = false;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^[USAPIConnection getTeamById:1 controller:testController];);
//dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^NSLog(@"HELLO FROM ASYNC QUEUE"););
【问题讨论】:
如果我错了,请纠正我,但是主线程不会在任何地方等待,所以当应该调用asynchronousSuccessfulWithObject
时,程序已经不再运行了
@toasted_flakes 这是通过测试运行的,所以当测试 testGetTeamById 运行时,while 循环有一个短暂的等待,直到完成或大约 30 秒过去。
错误可能仍然来自那里,因为在 XCTest 中没有运行循环。要调试 XCTest 的异步行为,您可以从运行虚拟块开始,而不是使用 AFNetworking。类似于dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^ NSLog(@"Hello from async queue"); );
@toasted_flakes 我不确定那会完成什么。你能进一步解释一下吗?
如果我对 XCTest 框架的理解是正确的,NSLog
将无法运行,因为缺少适当的 NSRunLoop
或等效项。然后我们就可以排除AFNetworking具体使用中的任何错误
【参考方案1】:
Xcode 6(撰写本文时尚未发布)中的 XCTest 支持异步方法的测试。
这是 Swift 中的一个小 sn-p,它显示了它的外观:
假设你有一个以完成函数为参数的异步方法:
func doSomethingAsync(completion:(result: Int?, error: Int?) -> ())
现在,您想测试此异步函数是否成功执行,或者您想测试您在延续(完成处理程序)中定义的一些代码:
func testAsyncFunction()
let expect = self.expectationWithDescription("completion handler called")
doSomethingAsync (result, error) -> () in
if let value = result?
println("Result: \(value)")
else
println("Error: \(error!)")
expect.fulfill()
waitForExpectationsWithTimeout(1000, handler: nil)
您可以在 XCTest 的标题中阅读有关 XCTest self.expectationWithDescription:
fulfill
和 waitForExpectationsWithTimeout:
的新方法的更多信息。
我现在正在使用这个新的异步测试工具进行单元测试。只是缺少一些功能,例如在 fulfill
旁边有一个方法 reject
和一个可选的用于记录的字符串参数。 IMO,它看起来很吸引人,到目前为止效果很好。所以,我真的鼓励你看看 Xcode 测试版;
与此同时,您可能会发现一个“promise”库适用于实现异步方法的测试。我建议在这个论坛中多次使用 RXPromise 库(我是作者)进行单元测试。 ;)
【讨论】:
除了@CouchDeveloper 回答的内容之外,我建议使用 OHHTTPStubs 来存根服务器响应。 github.com/AliSoftware/OHHTTPStubs【参考方案2】:在 UnitTest 中进行异步调用需要标志之类的东西。这里讨论的太多了:
How to unit test asynchronous APIs?
【讨论】:
以上是关于AFNetworking 单元测试的主要内容,如果未能解决你的问题,请参考以下文章
生成新单元格时清除集合视图单元格(iOS7 - AFNetworking)