HTTP 服务器在 Cocoa 应用程序中工作,但在测试用例中不起作用——运行循环问题?
我正在尝试向此 SimpleHTTPServer 示例 添加 GHUnit 测试用例。该示例包括一个对我来说运行良好的 Cocoa 应用程序。但我无法在测试用例中复制该行为。
这是测试类:
#import <GHUnit/GHUnit.h>
#import "SimpleHTTPServer.h"
@interface ServerTest : GHTestCase
{
SimpleHTTPServer *server;
}
@end
@implementation ServerTest
-(void)setUpClass
{
[[NSRunLoop currentRunLoop] run];
}
- (NSString*)requestToURL:(NSString*)urlString error:(NSError**)error
{
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:1];
NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:error];
NSString *page = nil;
if (error == nil)
{
NSStringEncoding responseEncoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)[response textEncodingName]));
page = [[NSString alloc] initWithData:data encoding:responseEncoding];
[page autorelease];
}
return page;
}
- (void)testPortReuse
{
unsigned int port = 50001;
NSError *error = nil;
NSString *path, *url;
server = [[SimpleHTTPServer alloc] initWithTCPPort:port delegate:self];
sleep(10);
path = @"/x/y/z";
url = [NSString stringWithFormat:@"http://localhost:%u%@", port, path];
[self requestToURL:url error:&error];
GHAssertNil(error, @"%@ : %@", url, error);
[server release];
}
- (void)processURL:(NSURL *)path connection:(SimpleHTTPConnection *)connection
{
NSLog(@"processURL");
}
- (void)stopProcessing
{
NSLog(@"stopProcessing");
}
@end
我尝试通过 NSURLRequest 发送请求,也尝试通过网络浏览器(在睡眠期间)发送请求。委托方法 -processURL
和 -stopProcessing
永远不会被调用。问题似乎是 SimpleHTTPServer -initWithTCPPort:delegate:
中的 [fileHandle acceptConnectionInBackgroundAndNotify]
不会导致任何 NSFileHandleConnectionAcceptedNotifications 到达 NSNotificationCenter - 所以我怀疑涉及运行循环的问题。
问题似乎出在 NSFileHandle 上,而不是 NSNotificationCenter 上,因为当将 [nc postNotificationName:NSFileHandleConnectionAcceptedNotification object:nil]
添加到 initWithTCPPort:delegate:
的末尾时, NSNotificationCenter 确实收到了通知。
I'm trying to add a GHUnit test case to this SimpleHTTPServer example. The example include a Cocoa application that works fine for me. But I can't duplicate the behavior in a test case.
Here is the test class:
#import <GHUnit/GHUnit.h>
#import "SimpleHTTPServer.h"
@interface ServerTest : GHTestCase
{
SimpleHTTPServer *server;
}
@end
@implementation ServerTest
-(void)setUpClass
{
[[NSRunLoop currentRunLoop] run];
}
- (NSString*)requestToURL:(NSString*)urlString error:(NSError**)error
{
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:1];
NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:error];
NSString *page = nil;
if (error == nil)
{
NSStringEncoding responseEncoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)[response textEncodingName]));
page = [[NSString alloc] initWithData:data encoding:responseEncoding];
[page autorelease];
}
return page;
}
- (void)testPortReuse
{
unsigned int port = 50001;
NSError *error = nil;
NSString *path, *url;
server = [[SimpleHTTPServer alloc] initWithTCPPort:port delegate:self];
sleep(10);
path = @"/x/y/z";
url = [NSString stringWithFormat:@"http://localhost:%u%@", port, path];
[self requestToURL:url error:&error];
GHAssertNil(error, @"%@ : %@", url, error);
[server release];
}
- (void)processURL:(NSURL *)path connection:(SimpleHTTPConnection *)connection
{
NSLog(@"processURL");
}
- (void)stopProcessing
{
NSLog(@"stopProcessing");
}
@end
I've tried sending requests via NSURLRequest and also (during the sleep
) via a web browser. The delegate methods -processURL
and -stopProcessing
are never called. The problem seems to be that [fileHandle acceptConnectionInBackgroundAndNotify]
in SimpleHTTPServer -initWithTCPPort:delegate:
is not causing any NSFileHandleConnectionAcceptedNotifications to reach the NSNotificationCenter -- so I suspect a problem involving run loops.
The problem seems to be with the NSFileHandle, not the NSNotificationCenter, because when [nc postNotificationName:NSFileHandleConnectionAcceptedNotification object:nil]
is added to the end of initWithTCPPort:delegate:
, the NSNotificationCenter does get the notification.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
应该是:
error
这里是传入的指向 NSError* 的指针 - 只有当调用者传递 nil 而不是对 NSError* 对象的引用时,它才会是 nil,这不是你的-testPortReuse
方法可以。取消引用它也是不正确的(如
if (*error == nil)
所示),因为错误参数不能保证在出错时设置为 nil。返回值指示错误情况,并且仅当存在错误时,错误参数中返回的值才有意义或可靠。始终检查返回值以确定是否发生错误,然后仅在确实出现错误时才检查错误参数以获取详细信息。换句话说,正如上面所写,您的
-requestToURL:error:
方法无法处理成功。很像查理辛。 :-)That should be:
error
here is the passed-in pointer to an NSError* - it will only be nil if the caller passed nil instead of a reference to an NSError* object, which isn't what your-testPortReuse
method does.It would also be incorrect to dereference it (as in
if (*error == nil)
), because error arguments are not guaranteed to be set to nil upon error. The return value indicates an error condition, and the value returned in the error argument is only meaningful or reliable if there is an error. Always check the return value to determine if an error happened, then check the error parameter for details only if something did in fact go wrong.In other words, as it's written above, your
-requestToURL:error:
method is incapable of handling success. Much like Charlie Sheen. :-)