2016-04-08 83 views
0

我正在嘗試通過NSURLSession在異步dataTaskWithRequest上設置自定義委託。我已經建立了協議並實現了委託方法,但我一直在弄清楚我是否正確實現了它,以及如何對它進行單元測試。具體來說,我想測試委託在調用之後是否返回某些內容,並使用實時API調用進行測試。我試過通過這裏建議的方法(OCUnit test for protocols/callbacks/delegate in Objective-C)進行測試,但測試失敗,可能是因爲我錯過了某些東西,或者沒有考慮到異步調用。下面是代表實施代碼和單元測試的代碼。爲NSURLSession設置委託並對其進行單元測試

代表協議聲明:

#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 
+1

我[寫了一篇博客文章](http://swiftandpainless.com/an-easy-way-to-stub-nsurlsession/)關於我如何測試NSURLSession。也許這有幫助。 – dasdom

+0

@dasdom感謝您的鏈接,我會在重新構建我的其他Swift應用程序時參考它。 –

回答

1

好吧我在蘋果的NSURLSession文檔和博客http://www.infinite-loop.dk/blog/2011/04/unittesting-asynchronous-network-access/的幫助下自己想出了它。我現在已經使用實時URL進行了測試,當我將API模擬添加到單元測試並使單元測試更加健壯時,我會更新答案。

簡而言之,NSURLSession有其自己的委託方法,在這種情況下,使用dataTaskWithRequest時,可以設置NSURLSessionDataDelegate並用於檢索API結果。

委託聲明的代碼大部分是正確的,我只需要在頭文件中將NSURLSessionDelegate更改爲NSURLSessionDataDelegate

單元測試需要一些設置,但是非常簡單。它涉及使用NSURLSession調用初始化該類,將該對象的代理設置爲self,並初始化一個標誌變量爲NO。代表被調用時,標誌變量將被設置爲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