Сбой GHUnit при запуске утверждения в блоке обратного вызова вместо отображения ошибки на внешнем интерфейсе - PullRequest
2 голосов
/ 14 февраля 2012

Использование любого утверждения в обратном вызове приводит к сбою приложения GH-Unit. Утверждения отлично работают в других местах.

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

Но я не понимаю, как я могу использовать это решение в моем случае.

- (void)testLoadMyProfile {

    void(^successCallback)(NSString*);
    successCallback = ^(NSString* response) {

        NSRange textRange;
        textRange =[[response lowercaseString] rangeOfString:[@"syntactically incorrect" lowercaseString]];

        if(textRange.location != NSNotFound) {
            GHFail(@"the request was syntactically incorrect");
        }

        NSDictionary *d;        
        @try {
            d = [response JSONValue];    
        } @catch (NSException *exception) {
            GHAssertNotNil(d, @"The response was not a valid JSONValue");
        }

        GHAssertNotNil([d objectForKey:@"memberId"], @"memberId wasn't in response");
        GHAssertNotNil([d objectForKey:@"profile"], @"profile wasn't in response");
        GHAssertNotNil([d objectForKey:@"name"], @"profile wasn't in response");
        GHAssertNotNil([d objectForKey:@"surnamez"], @"profile wasn't in response");
    };

    void(^errorCallback)(NSString*);
    errorCallback = ^(NSString* response) {
        GHFail(@"the error callback was called");
    };    

    // this is using ASIHTTPRequest to retrieve data
    [[RestAPIConnector sharedInstance] loadMyProfile:successCallback :errorCallback];
}

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

- (void)failWithException:(NSException *)exception {

}

Ответы [ 2 ]

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

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

Сначала вы должны создать подкласс GHAsyncTestCase

-(void)testGetRequest{
    [self prepare]; //prepare for hook the run loop

    PLRequest *req=[PLRequest requestWithURL:[NSURL URLWithString:@"http://m.baidu.com"]];
    req.finishCallback=^(PLRequest *req){
        NSData *d=req.respondData;

        NSString *s=[NSString stringWithUTF8String:[d bytes]];

        GHTestLog(@"Finish:%@", s);
        [self notify:kGHUnitWaitStatusSuccess]; //here to return
    };

    [req start];

    [self waitForStatus:kGHUnitWaitStatusSuccess timeout:15]; //wait for your block change Status then if timeout you will get a 'crash'

}
0 голосов
/ 24 января 2013

Ответ (на который вы указывали) здесь должен работать и для вас.

Так что вы должны реализовать GHAsyncTestCase, как упоминал Трэвис ранее.Имея базовый класс Async, вы можете использовать waitForStatus:timeout: и соответствующие notify:forSelector: методы.Все утверждения должны быть сделаны после waitForStatus:timeout:.Этот метод приостанавливает цикл выполнения и ожидает завершения обратного вызова.

Посмотрите выборки GHUnit , если вам нужна дополнительная информация об асинхронных тестах.

Так что в вашем случае я бы попробовал что-то вроде этого:

- (void)testLoadMyProfile {

//Local variable for later assertion. __block is necessary to use the variable in the block.  
__block NSDictionary *d = nil;  

//Preparing.  
[self prepare];

void(^successCallback)(NSString*);
successCallback = ^(NSString* response) {

    NSRange textRange;
    textRange =[[response lowercaseString] rangeOfString:[@"syntactically incorrect" lowercaseString]];

    if(textRange.location != NSNotFound) {
        GHFail(@"the request was syntactically incorrect");
    }

    // Declared before.
    // NSDictionary *d;

    @try {

        d = [response JSONValue];    

    } @catch (NSException *exception) {

        // We'll check that later.
        // GHAssertNotNil(d, @"The response was not a valid JSONValue");
    }

    // Later.
    //GHAssertNotNil([d objectForKey:@"memberId"], @"memberId wasn't in response");
    //GHAssertNotNil([d objectForKey:@"profile"], @"profile wasn't in response");
    //GHAssertNotNil([d objectForKey:@"name"], @"profile wasn't in response");
    //GHAssertNotNil([d objectForKey:@"surnamez"], @"profile wasn't in response");

    // we notify ourself that we are done. selector should point to this method!  
   [self notify:kGHUnitWaitStatusSuccess forSelector:@selector(testLoadMyProfile)];  

};

void(^errorCallback)(NSString*);
errorCallback = ^(NSString* response) {
    GHFail(@"the error callback was called");

    // in this case we do notify ourself that the request failed.  
   [self notify:kGHUnitWaitStatusFailure forSelector:@selector(testLoadMyProfile)];

};    

[[RestAPIConnector sharedInstance] loadMyProfile:successCallback :errorCallback];

// This line pauses the runloop for the length of the timeout
[self waitForStatus:kGHUnitWaitStatusSuccess timeout:10.0];

// And finally after this line you can do your assertions. As the code pauses until you notify it or the timeout fires.
GHAssertNotNil(d, @"The response was not a valid JSONValue");
GHAssertNotNil([d objectForKey:@"memberId"], @"memberId wasn't in response");
GHAssertNotNil([d objectForKey:@"profile"], @"profile wasn't in response");
GHAssertNotNil([d objectForKey:@"name"], @"profile wasn't in response");
GHAssertNotNil([d objectForKey:@"surnamez"], @"profile wasn't in response");

}

Таким образом, все утверждения для асинхронных тестов необходимо выполнять после waitForStatus:timeout:.и не забудьте notify:forSelector.

...