2015-01-17 2 views
1

У меня есть следующий код теста случай:Использование AFHTTPRequestOperation в XCTests

- (void)testExample { 
    // URL https://api.spotify.com/v1/search?q=album%3AJustified%20artist%3AJustin%20Timberlake&type=album 


    dispatch_semaphore_t sem = dispatch_semaphore_create(0); 
    [[AFHTTPRequestOperationManager manager] GET:@"https://api.spotify.com/v1/search" 
             parameters:@{@"q":@"album:Justified artist:Justin Timberlake", 
                @"type":@"album"} 
             success:^(AFHTTPRequestOperation *operation, id responseObject) { 
              dispatch_semaphore_signal(sem); 
             } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 

             } 
    ]; 
    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); 

    // This is an example of a functional test case. 
    XCTAssert(YES, @"Pass"); 
} 

Я ожидал, что тестовый пример, чтобы блокировать и ждать запроса HTTP, чтобы закончить. Странная вещь, что AFHTTPRequestOperation никогда не достигает блока успеха, даже URL является допустимым. Если я использую следующий код вне XCTest, это не произойдет, блок успеха будет выполнен. Кто-нибудь видел это раньше?

ответ

1

Несколько наблюдений:

  1. Ваш тест замерзает, потому что AFNetworking отправляет свои завершающие блоки в основную очередь. Но вы заблокировали основной поток dispatch_semaphore_wait, что привело к тупиковой ситуации.

    Вы можете решить эту проблему, установив Управляющего completionQueue быть глобальной очереди для целей испытания, тем самым устраняя затор, вызванный семафора на главной теме:

    - (void)testExample { 
        dispatch_semaphore_t sem = dispatch_semaphore_create(0); 
    
        AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
    
        manager.completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    
        [manager GET:@"https://api.spotify.com/v1/search" parameters:@{@"q":@"album:Justified artist:Justin Timberlake", @"type":@"album"} success:^(AFHTTPRequestOperation *operation, id responseObject) { 
         XCTAssert(YES, @"Pass"); // you might want more rigorous test of results here 
    
         dispatch_semaphore_signal(sem); 
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
         XCTFail(@"%@", error.localizedDescription); 
    
         dispatch_semaphore_signal(sem); 
        }]; 
    
        dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); 
    } 
    
  2. Примечание, в настоящее время один будет использовать XCTestExpectation для выполнения асинхронных тестов. Это устраняет необходимость семафора и, по совпадению, решает проблему взаимоблокировки, тоже:

    - (void)testExample { 
        XCTestExpectation *expectation = [self expectationWithDescription:@"asynchronous request"]; 
    
        AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
    
        [manager GET:@"https://api.spotify.com/v1/search" parameters:@{@"q":@"album:Justified artist:Justin Timberlake", @"type":@"album"} success:^(AFHTTPRequestOperation *operation, id responseObject) { 
         XCTAssert(YES, @"Pass"); // you might want more rigorous test of results here 
    
         [expectation fulfill]; 
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
         XCTFail(@"%@", error.localizedDescription); 
    
         [expectation fulfill]; 
        }]; 
    
        [self waitForExpectationsWithTimeout:30.0 handler:nil]; 
    } 
    
  3. Кстати, использовать ли вы XCTestExpectation или семафор, убедитесь, что оба блока успеха и неудачи как удовлетворить ожидания/семафор.

+0

Да, я решил, что второе решение работает. спасибо – BullOnTheWay