2010-07-16 33 views
1

我在學習如何使用單元測試在iPhone上使用NSInputStream類。我可以讓NSStream使用輪詢方法從文件中讀取數據,但由於某種原因委託/事件方法不起作用。在OCUnitTest中無法接收NSInputStream事件

我已經發布了下面的相關代碼。請忽略內存泄漏錯誤等,因爲我只是試圖確保我知道如何在沙盒環境中使用NSStream類,然後將其滾動到我的大型項目中。

我想知道如果我錯過了一些關於運行循環如何工作的東西?

這是創建流文件類以從文件讀取的邏輯測試。

#import "StreamingTests.h" 
#import "Streamer.h" 

@implementation StreamingTests 

- (void) testStream { 
    NSLog(@"Starting stream test."); 
    Streamer * streamer = [[Streamer alloc] init]; 

    streamer.usePolling = NO; 
    streamer.readingStream = YES; 
    NSThread * readThread = [[NSThread alloc] initWithTarget:streamer selector:@selector(startStreamRead:) object:nil]; 
    [readThread start]; 
    while(streamer.readingStream) { 
     [NSThread sleepForTimeInterval:0.5]; 
    } 
    [readThread cancel]; 
} 

@end 

這是一個簡單的測試輔助對象,其從NSStream讀取。當usePolling == YES時,它讀取數據並輸出適當的NSLog消息。但是,如果usePolling == NO,則從不調用委託流事件函數。

@implementation Streamer 
@synthesize readingStream, usePolling; 

- (void) startStreamRead:(NSObject*) context { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 
    NSLog(@"starting stream read."); 
    readingStream = YES; 
    /* 
    NSURL * url = [NSURL URLWithString:@"http://www.google.com"]; 
    NSLog(@"Loading: %@",[url description]); 
    NSInputStream * inStream = [[NSInputStream alloc] initWithURL:url]; 
    */ 
    NSInputStream * inStream = [[NSInputStream alloc] initWithFileAtPath:@"sample.ttc"]; 

    if(!usePolling) { 

     [inStream setDelegate: self]; 
     [inStream scheduleInRunLoop: [NSRunLoop currentRunLoop] 
          forMode: NSDefaultRunLoopMode]; 


    } 
    [inStream open]; 

    if(usePolling) { 
     while(1) { 
      if([inStream hasBytesAvailable]) { 
       uint8_t buf[1024]; 
       unsigned int len = 0; 
       len = [(NSInputStream *)inStream read:buf maxLength:1024]; 
       NSLog(@"Read: %d",len); 
      } 
      NSStreamStatus status = [inStream streamStatus]; 
      if(status != NSStreamStatusOpen && status != NSStreamStatusOpening) { 
       NSLog(@"Stream not open."); 
       break; 
      } 
     } 
     readingStream = NO; 

     NSStreamStatus status = [inStream streamStatus]; 
     NSError * error = [inStream streamError]; 
     NSLog(@"Status: %d Error Desc: %@ Reason: %@",(int)status,[error localizedDescription], [error localizedFailureReason]); 

     [pool release]; 
    } 

} 


- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode { 
    NSMutableData * _data = nil; 
    NSNumber * bytesRead = nil; 
    NSLog(@"Event fired."); 
    switch(eventCode) { 
     case NSStreamEventHasBytesAvailable: 
     { 
      if(!_data) { 
       _data = [[NSMutableData data] retain]; 
      } 
      uint8_t buf[1024]; 
      unsigned int len = 0; 
      len = [(NSInputStream *)stream read:buf maxLength:1024]; 
      if(len) { 
       [_data appendBytes:(const void *)buf length:len]; 
       // bytesRead is an instance variable of type NSNumber. 
       //[bytesRead setIntValue:[bytesRead intValue]+len]; 
       NSLog(@"Read %d bytes",len); 
      } else { 
       NSLog(@"no buffer!"); 
      } 
      break; 
     } 
     case NSStreamEventEndEncountered: 
     { 
      [stream close]; 
      [stream removeFromRunLoop:[NSRunLoop currentRunLoop] 
           forMode:NSDefaultRunLoopMode]; 
      [stream release]; 
      stream = nil; // stream is ivar, so reinit it 
      readingStream = NO; 
      break; 
     } 
     default: 
     { 
      NSLog(@"Another event occurred."); 
      break; 
     } 
      // continued ... 
    } 
} 

@end 

由於提前,

b

回答

0

它應是運行的循環被阻斷由於單元測試正在執行的原因。您可以參考the NSRunLoop documentation,其中方法

runUntilDate: 

可能會幫助你運行像這樣的單元測試的執行線程的主運行循環:

[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; 

這讓運行循環運行的1秒給它時間來處理你的文件的一部分。應該指出的是,這不能爲單元測試提供可靠的方法(因爲時間間隔可能因運行循環大小而異),因此可能不適用。通過給您的單元,其可用於檢查輸入流的狀態的接口的讀取操作(用讀取結束狀態),諸如

-(BOOL)hasFinishedReadingFile 

單元測試可以重複執行運行循環,直到上述方法返回TRUE並且文件被完全讀取。

增加:This question on stackoverflow也以不同的方式處理問題。