在回调中使用任何断言都会导致GH单元应用程序崩溃。断言在其他地方也很有效。
这里还有一个类似的问题:为什么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 {
}
您应该更改Status以停止块运行循环,查看我的评论:(对不起我的英语不好)
首先,您必须为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'
}
这里的答案(您所指的)也应该适用于您。
因此,您应该像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
。