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

The answer (you were pointing to) here should work for you, too.

So you should implement GHAsyncTestCase as Travis mentioned before. Having the Async base class you can use waitForStatus:timeout: and the corresponding notify:forSelector: methods. All assertions need to be done after waitForStatus:timeout:. This method pauses the runloop and waits until your callback is done.

Take a look at the samples of GHUnit if you need more info about the async tests.

So in your case i would try something like this:

- (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");

}

So all assertions for asynchronous tests need to done after waitForStatus:timeout:. and don't forget the notify:forSelector.

于 2013-01-24T01:45:30.240 回答