Почему ложное утверждение в асинхронном тесте в GHUnit разбивает приложение вместо того, чтобы просто пропустить тест?

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

Я использую GHAsyncTestCase, чтобы протестировать собственный NSOperation. Я устанавливаю тестовый пример в качестве делегата для объекта операции, и я вызываю didFinishAsyncOperation в основном потоке, когда это делается.

Когда утверждение терпит неудачу, оно вызывает исключение, которое должно быть уловлено тестовым случаем, чтобы сделать тест "неудачным". Но вместо этого ожидаемого поведения мое приложение прерывается Xcode, как только утверждение терпит неудачу.

*** Завершение приложения из-за неперехваченного исключения "GHTestFailureException", причина: "NO" должна быть ИСТИНА. Это должно вызвать неудачный тест, но вместо этого отключает мое приложение.

Я, очевидно, что-то делаю неправильно. Кто может мне сказать?

@interface TestServiceAPI : GHAsyncTestCase
@end

@implementation TestServiceAPI

    - (BOOL)shouldRunOnMainThread
    {
        return YES;
    }

    - (void)testAsyncOperation
    {
        [self prepare];

        MyOperation *op = [[[MyOperation alloc] init] autorelease];

        op.delegate = self; // delegate method is called on the main thread.

        [self.operationQueue addOperation:op];

        [self waitForStatus:kGHUnitWaitStatusSuccess timeout:1.0];
    }

    - (void)didFinishAsyncOperation
    {
        GHAssertTrue(NO, @"This should trigger a failed test, but crashes my app instead.");

        [self notify:kGHUnitWaitStatusSuccess forSelector:@selector(testAsyncOperation)];
    }

@end

Ответ 1

Я рылся в течение недели, чтобы найти решение этого, когда я наконец поймал перерыв. Это было немного странно, когда у меня не было взглядов на вопрос о щедрости, и никто не хотел пытаться ответить. Я думал, что вопрос может быть глупым, но не было никаких нисходящих спусков, и никто не мог его исправить. Может ли StackOverflow стать насыщенным?

Решение.

Трюк состоит в том, чтобы не утверждать ничего из метода обратного вызова, но вернул утверждения в исходный тест. Метод wait фактически блокирует поток, о котором я раньше не думал. Если ваш асинхронный обратный вызов получает какие-либо значения, просто сохраните их в ivar или свойстве, а затем сделайте утверждения на их основе в исходном методе тестирования.

Это касается утверждений, не вызывающих сбоев.

- (void)testAsyncOperation
{
    [self prepare];

    MyOperation *op = [[[MyOperation alloc] init] autorelease];

    op.delegate = self; // delegate method is called on the main thread.

    [self.operationQueue addOperation:op];

    // The `waitfForStatus:timeout` method will block this thread.
    [self waitForStatus:kGHUnitWaitStatusSuccess timeout:1.0];

    // And after the callback finishes, it continues here.
    GHAssertTrue(NO, @"This triggers a failed test without anything crashing.");
}

- (void)didFinishAsyncOperation
{
    [self notify:kGHUnitWaitStatusSuccess forSelector:@selector(testAsyncOperation)];
}

Ответ 2

Посмотрите навигатор Xcode Breakpoints, удалите все контрольные точки исключения, что все!!!

Ответ 3

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

// Override any exceptions; By default exceptions are raised, causing a test failure
- (void)failWithException:(NSException *)exception { }

Чтобы исключить исключения, но проще использовать GHAssertTrueNoThrow вместо макроса GHAssertTrue.