Семафор никогда не сигнализирует в модульном тестировании (dispatch_get_main_que () никогда не запускается?) - PullRequest
1 голос
/ 23 марта 2012

Я нашел этот поток в качестве ссылки: Как дождаться окончания асинхронно отправленного блока? и использую этот код (сигнализирующий семафор внутри блока), чтобы дождаться завершения моего потока перед завершение теста.

Однако мой семафор никогда не сигнализирует, что это сделано ... поэтому я прошелся по коду и обнаружил, что код внутри этого небольшого фрагмента никогда не запускается:

        dispatch_async(dispatch_get_main_queue(), ^{
            [self removeDownloadSpinner];
            block(callback);
        });

dispatch_get_main_queue () не срабатывает, когда я выполняю модульное тестирование? Если нет, то как вы тестируете асинхронные блоки?

РЕДАКТИРОВАТЬ (вот немного больше кода): В основном у меня есть класс «ServerRequest», который содержит все входящие / исходящие сетевые запросы для приложения. Один из методов такой (блок завершения определен по типу):

+(void)checkPlayerCode:(NSString *)playerCode completionHandler:(PlayerCompletionBlock)block {
  [self addDownloadSpinner];
  NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@/players/%@",kBaseURL, playerCode]];
  NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
  [ServerConnectionRequest sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    NSDictionary *p = [data objectFromJSONData];
    Player *player = [[Player alloc] init];
    player.last_name = [p objectForKey:@"last_name"];
    if (!error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self removeDownloadSpinner];
            block(player);
        });

    }
}]; 

}

Который вызывается из контроллера uiview следующим образом:

    [ServerRequest checkPlayerCode:codeCell.textField.text completionHandler:^(Player *p){
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"wooo block" message:@"works" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];
    [alert show];
}];

Однако блок dispatch_get_main_queue () никогда не срабатывает.

Ответы [ 2 ]

1 голос
/ 02 апреля 2012

Проблема в том, что вы ожидаете семафор в главном потоке и одновременно пытаетесь выполнить некоторый код на главном шаге с помощью dispatch_async (dispatch_get_main_queue (), ...). Попробуйте использовать runUntilDate для NSRunLoop, например

__block volatile bool loadComplete = false;
dispatch_async(dispatch_get_main_queue(), ^(..)
                                                {                                                                     
                                                    ..
                                                    loadComplete = true;
                                                });

NSDate* startTime = [NSDate date];
while ( !loadComplete ) 
{
    NSDate* nextTry = [NSDate dateWithTimeIntervalSinceNow:0.1];
    [[NSRunLoop currentRunLoop] runUntilDate:nextTry]; 

    if ( [nextTry timeIntervalSinceDate:startTime] > ../* some appropriate time interval here */ )
        STAssertTrue(false, @"TIMEOUT");
}

// Assertions here
1 голос
/ 23 марта 2012

Нет проблем с выполнением многопоточного кода в модульных тестах, и я запустил в них все виды кода диспетчеризации.

Когда вы говорите, что пошагово прошёл код, вы имеете в виду, что вы буквально пошагово прошли через отладчик. Если это так, и вы предполагали, что код не запустился, потому что отладчик не остановился в блоке, вы должны помнить, что он будет выполняться в другом потоке, и вам потребуется точка останова, чтобы остановить его.

Так что я бы назначил точки останова в блоке.

Во-вторых, если вы тестируете код, запущенный из основного потока, это не будет работать, потому что вы не можете асинхронно выполнить некоторый код в том же потоке, в котором вы находитесь. Код модульного теста должен выполняться в фоновом потоке.

Тогда возникает проблема времени выполнения. Поскольку вы запускаете асинхронный блок, возможно, он еще не выполнен.

Проверка асинхронных вызовов означает, что, вероятно, ваш код, приведенный выше, должен будет дождаться завершения асинхронного вызова, прежде чем он сможет подтвердить все, что он мог сделать. В этом случае вы должны учитывать, что это должна быть синхронизация, а не асинхронность.

Вам нужно показать больше кода, я думаю: -)

...