2

コールバックでアサーションを使用すると、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 {

}
4

2 に答える 2

1

ステータスを変更してブロック実行ループを停止する必要があります。私のコメントを確認してください: (英語が下手で申し訳ありません)

まず、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'

}
于 2012-04-14T13:24:42.843 に答える
0

ここでの答え(あなたが指していた)もあなたのために働くはずです。

そのため、前述の Travis のように 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

于 2013-01-24T01:45:30.240 に答える