我正在尝试使用单元测试来测试网络。当在测试之外调用时,loginWithUserName:password: method将正确失败,外部故障块将被调用。当从我的测试方法中调用时,不会调用失败块(也不会调用成功块)。
我认为我的信号量等待可能导致网络也在等待,但我不会这么认为,因为它在另一个线程上。我希望它在不同的线程上,这样我就可以进行异步调用了。我能把这个修好吗?我应该用不同的技术吗?
我的测试方法设置如下:
typedef void (^CompleteBlock)();
- (void)testLogin {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self callLoginWithCompletion:^{
XCTAssertTrue(true, @"login Complete"); // expand on this when I get basic premise working
NSLog(@"asserted true");
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
- (void)callLoginWithCompletion:(CompleteBlock)completeBlock {
NSLog(@"login method called");
[[NSNotificationCenter defaultCenter] addObserverForName:kLoginComplete
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
completeBlock();
}];
[Network loginWithUserName:@"dummyUser" password:@"dummyPassword"];
}我的登录方法是这样的:静态AFNetworkReachabilityManager *_reachabilityManager;
+ (AFHTTPRequestOperationManager *)gatewayClient {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_gatewayClient = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:kGatewayBaseURL]];
_gatewayClient.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/plain"];
});
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
securityPolicy.allowInvalidCertificates = YES;
[AFHTTPRequestOperationManager manager].securityPolicy = securityPolicy;
return _gatewayClient;
}
+ (NSString *)baseURLForType:(NSString *)type method:(NSString *)method {
return [NSString stringWithFormat:@"api/%@/%@", type, method];
}
+ (void)loginWithUserName:(NSString *)userName password:(NSString *)password {
[Network.gatewayClient
GET:[self baseURLForType:@"auth"
method:@"getpubtoken"]
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
_authToken = responseObject;
NSDictionary *parameters = @{
@"UserId": userName
, @"Password": password
, kApiVersion: kApiVersion
, kApiKey: kApiKeyValue
, kAuthToken: _authToken
, kFundraisingPlatform: @(Blackbaud)
};
[Network.gatewayClient
POST:[self baseURLForType:@"auth"
method:@"loginfundraiser"]
parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary *responseDict = (NSDictionary *)responseObject;
NSDictionary *userInfo = nil;
_authToken = responseDict[kAuthToken];
if ([responseDict[@"Successful"] boolValue]) {
userInfo = @{ kAuthToken: responseObject[kAuthToken] };
} else {
userInfo = @{ @"error": [[NSError alloc] initWithDomain:@"Authorization"
code:-1000
userInfo:@{ @"message": responseDict[@"ExtendedMessages"] }] };
}
[[NSNotificationCenter defaultCenter] postNotificationName:kLoginComplete
object:nil
userInfo:userInfo];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSDictionary *userInfo = @{ @"error": error };
[[NSNotificationCenter defaultCenter] postNotificationName:kLoginComplete
object:nil
userInfo:userInfo];
}];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSDictionary *userInfo = @{ @"error": error };
[[NSNotificationCenter defaultCenter] postNotificationName:kLoginComplete
object:nil
userInfo:userInfo];
}];
}发布于 2014-05-09 17:16:04
好吧..。主要问题是AFNetworking、和的队列,通知位于主线程上。信号量阻塞了主线程,因此两种响应都被阻塞。
为了进行测试,必须指定一个新的NSOperationQueue来代替mainQueue。对于网络类,必须指定一个新的completionQueue。似乎没有在这些方法上设置默认completionQueue的方法。这方面的问题已经开始。
新的测试代码和网络子集如下所示。
@implementation NetworkTests
NSOperationQueue * testOperationQueue;
- (void)setUp {
[super setUp];
testOperationQueue = [[NSOperationQueue alloc] init];
}
- (void)testLogin {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[[NSNotificationCenter defaultCenter] addObserverForName:kLoginComplete
object:nil
queue:testOperationQueue
usingBlock:^(NSNotification *note) {
XCTAssertTrue(true, @"login Complete"); // expand on this when I get basic premise working
NSLog(@"asserted true");
dispatch_semaphore_signal(sema);
}];
[Network loginWithUserName:@"testname" password:@"password"];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
@end对于该网络,它有如下内容:
static dispatch_queue_t completionQueue; // initialized when the _gatewayClient object is created
+ (void)loginWithUserName:(NSString *)userName password:(NSString *)password {
AFHTTPRequestOperation *outerOperation =
[Network.gatewayClient
GET:[self baseURLForType:@"auth"
method:@"getpubtoken"]
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
// do stuff here
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSDictionary *userInfo = @{ @"error": error };
[[NSNotificationCenter defaultCenter] postNotificationName:kLoginComplete
object:nil
userInfo:userInfo];
}];
outerOperation.completionQueue = completionQueue;
}发布于 2017-04-10 08:45:41
我知道对于那些来到这个线程的answering.just来说已经太晚了,因为afnetwork有一个完成队列,它的缺省值是主队列。您可以将其更改为另一个队列,如后台队列,以避免锁定[AFHTTPSessionManager manager].completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);。
https://stackoverflow.com/questions/23567572
复制相似问题