我目前正在尝试通过NSURLSession在异步dataTaskWithRequest上设置自定义委托。我已经设置了协议并实现了委托方法,但我一直在弄清楚我是否已正确实现它,以及如何对其进行单元测试。具体来说,我想测试委托是否在调用后返回一些内容,并使用实时API调用进行测试。我已尝试通过此处建议的方法(OCUnit test for protocols/callbacks/delegate in Objective-C)进行测试,但测试失败,可能是因为我遗漏了某些内容或未考虑异步调用。下面是尝试委托实施和单元测试的代码。
委托协议声明:
#include "PtvApiPublic.h"
#ifndef PtvApiDelegate_h
#define PtvApiDelegate_h
@class PtvApi;
@protocol PtvApiDelegate <NSObject>
-(void) ptvApiHealthCheck: (PtvApi *) sender;
@end
#endif /* PtvApiDelegate_h */
标题文件:
#include "PtvApiDelegate.h"
#ifndef PtvApi_h
#define PtvApi_h
@interface PtvApi : NSObject
@property (nonatomic, weak) id <NSURLSessionDelegate> delegate;
- (void)ptvApiHealthCheck;
@end
#endif /* PtvApi_h */
PtvApi.m的片段
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonHMAC.h>
#import <CommonCrypto/CommonDigest.h>
#import "PtvApiPublic.h"
#import "PtvApiPrivate.h"
#import "PtvApiDelegate.h"
@implementation PtvApi
@synthesize delegate;
...
- (void)ptvApiHealthCheck
{
NSString *fullUrl = [self GenerateRequestUrl];
NSURLSession *apiSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:delegate delegateQueue:nil];
NSURL *apiUrl = [NSURL URLWithString: fullUrl];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:apiUrl];
[apiSession dataTaskWithRequest:urlRequest];
}
@end
单元测试:
#import <XCTest/XCTest.h>
#import "PtvApiPublic.h"
@interface APIDelegateTests : XCTestCase <NSURLSessionDelegate>
{
PtvApi *testApi;
BOOL callbackInvoked;
}
@end
@implementation APIDelegateTests
- (void)setUp {
[super setUp];
testApi = [[PtvApi alloc] init];
testApi.delegate = self;
}
- (void)tearDown {
testApi.delegate = nil;
[super tearDown];
}
- (void)testThatApiCallbackWorks {
[testApi ptvApiHealthCheck];
XCTAssert(callbackInvoked, @"Delegate should return something, I think...");
}
@end
答案 0 :(得分:1)
好吧,我借助于Apple的NSURLSession文档和http://www.infinite-loop.dk/blog/2011/04/unittesting-asynchronous-network-access/的博客来解决这个问题。我现在用实时网址对其进行了测试,当我将API模拟添加到单元测试并使单元测试更加健壮时,我会更新答案。
缺点是NSURLSession
有自己的委托方法,在这种情况下使用dataTaskWithRequest
,可以设置NSURLSessionDataDelegate
并用于检索API结果。
代理声明的代码大部分都是正确的,我只需要在头文件中将NSURLSessionDelegate
更改为NSURLSessionDataDelegate
。
单元测试需要一些设置,但其他方面非常简单。它涉及使用NSURLSession
调用初始化类,将对象的委托设置为self
,并将标志变量初始化为NO
。调用委托时,flag变量将设置为YES
,这是我最初测试的。完全设置的单元测试如下。
@interface APIDelegateTests : XCTestCase <NSURLSessionDataDelegate>
{
PtvApi *testApi;
BOOL callbackInvoked;
}
@end
@implementation APIDelegateTests
- (void)setUp {
[super setUp];
testApi = [[PtvApi alloc] init];
testApi.delegate = self;
callbackInvoked = NO;
}
- (void)tearDown {
testApi.delegate = nil;
[super tearDown];
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
callbackInvoked = YES;
}
// Method is credit to Claus Brooch.
// Retrieved from http://www.infinite-loop.dk/blog/2011/04/unittesting-asynchronous-network-access/ on 10/04/2016
- (BOOL)waitForCompletion:(NSTimeInterval)timeoutSecs {
NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeoutSecs];
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeoutDate];
if([timeoutDate timeIntervalSinceNow] < 0.0)
break;
} while (!callbackInvoked);
return callbackInvoked;
}
- (void)testThatApiCallbackWorks {
[testApi ptvApiHealthCheck];
XCTAssert([self waitForCompletion:30.0], @"Testing to see what happens here...");
}
@end