首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >信号量等待导致块AFNetworking?

信号量等待导致块AFNetworking?
EN

Stack Overflow用户
提问于 2014-05-09 14:47:10
回答 2查看 1.2K关注 0票数 4

我正在尝试使用单元测试来测试网络。当在测试之外调用时,loginWithUserName:password: method将正确失败,外部故障块将被调用。当从我的测试方法中调用时,不会调用失败块(也不会调用成功块)。

我认为我的信号量等待可能导致网络也在等待,但我不会这么认为,因为它在另一个线程上。我希望它在不同的线程上,这样我就可以进行异步调用了。我能把这个修好吗?我应该用不同的技术吗?

我的测试方法设置如下:

代码语言:javascript
复制
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;

代码语言:javascript
复制
+ (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];
     }];
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-05-09 17:16:04

好吧..。主要问题是AFNetworking、的队列,通知位于主线程上。信号量阻塞了主线程,因此两种响应都被阻塞。

为了进行测试,必须指定一个新的NSOperationQueue来代替mainQueue。对于网络类,必须指定一个新的completionQueue。似乎没有在这些方法上设置默认completionQueue的方法。这方面的问题已经开始。

新的测试代码和网络子集如下所示。

代码语言:javascript
复制
@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

对于该网络,它有如下内容:

代码语言:javascript
复制
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;
}
票数 2
EN

Stack Overflow用户

发布于 2017-04-10 08:45:41

我知道对于那些来到这个线程的answering.just来说已经太晚了,因为afnetwork有一个完成队列,它的缺省值是主队列。您可以将其更改为另一个队列,如后台队列,以避免锁定[AFHTTPSessionManager manager].completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23567572

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档