【问题标题】:Xcode - Unit test a network callXcode - 单元测试网络调用
【发布时间】:2015-04-18 11:56:29
【问题描述】:

我有以下要为其创建单元测试的代码。我想检查 self.response 是否不为零

- (void)downloadJson:(NSURL *)url {
  // Create a download task.
  NSURLSessionDataTask *task = [[NSURLSession sharedSession]
        dataTaskWithURL:url
      completionHandler:^(NSData *data, NSURLResponse *response,
                          NSError *error) {
        if (!error) {
          NSError *JSONError = nil;
          NSDictionary *dictionary =
              [NSJSONSerialization JSONObjectWithData:data
                                              options:0
                                                error:&JSONError];
          if (JSONError) {
            NSLog(@"Serialization error: %@", JSONError.localizedDescription);
          } else {
            NSLog(@"Response: %@", dictionary);
            self.response = dictionary;
          }
        } else {
          NSLog(@"Error: %@", error.localizedDescription);
        }
      }];
  // Start the task.
  [task resume];
}

我目前拥有的是

- (void)testDownloadJson {

  XCTestExpectation *expectation =
      [self expectationWithDescription:@"HTTP request"];
  [self.vc
      downloadJson:[NSURL URLWithString:@"a json file"]];

  [self waitForExpectationsWithTimeout:5
                               handler:^(NSError *error) {
                                 // handler is called on _either_ success or
                                 // failure
                                 if (error != nil) {
                                   XCTFail(@"timeout error: %@", error);
                                 } else {
                                   XCTAssertNotNil(
                                       self.vc.response,
                                       @"downloadJson failed to get data");
                                 }
                               }];
}

但这当然是不正确的。想知道是否有人可以帮助我了解如何编写此测试。

谢谢

【问题讨论】:

    标签: ios xcode xctest


    【解决方案1】:

    按照 Rob 发布的链接,我现在有了这个并且它可以工作了

    - (void)downloadJson:(NSURL*)url andCallback:(void (^)(NSDictionary*))callback
    {
        // Create a download task.
        NSURLSessionDataTask* task = [[NSURLSession sharedSession] dataTaskWithURL:url
                                                                 completionHandler:^(NSData* data,
                                                                                       NSURLResponse* response,
                                                                                       NSError* error) {
                                          if (!error)
                                          {
                                              NSError *JSONError = nil;
    
                                              NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data
                                                                                                         options:0
                                                                                                           error:&JSONError];
                                              if (JSONError)
                                              {
                                                  NSLog(@"Serialization error: %@", JSONError.localizedDescription);
                                              }
                                              else
                                              {
                                                  NSLog(@"Response: %@", dictionary);
                                                  self.response = dictionary;
                                                  callback(self.response);
                                              }
                                          }
                                          else
                                          {
                                              NSLog(@"Error: %@", error.localizedDescription);
                                          }
                                                                 }];
        // Start the task.
        [task resume];
    }
    

    和测试

    - (void)testDownloadJson
    {
        XCTestExpectation* expectation = [self expectationWithDescription:@"HTTP request"];
    
        [self.vc downloadJson:[NSURL URLWithString:@"a json file"] andCallback:^(NSDictionary* returnData) {
            XCTAssertNotNil(returnData, @"downloadJson failed to get data");
            [expectation fulfill];
        }];
    
        [self waitForExpectationsWithTimeout:10.0 handler:nil];
    }
    

    【讨论】:

      【解决方案2】:

      downloadJson 是否没有提供一些完成处理程序,一个可以在异步调用完成时调用的块?请参阅How do I unit test HTTP request and response using NSURLSession in iOS 7.1?,了解人们通常如何使用XCTestExpectation

      通常您将[expectation fulfill] 放在完成处理程序中,以便waitForExpectationsWithTimeout 知道它成功了。

      坦率地说,无论如何,为您的 downloadJson 方法设置一个完成块可能会很有用,因此您可能需要添加它。

      - (void)downloadJson:(NSURL *)url completionHandler:(void (^)(NSDictionary *responseObject, NSError *error))completionHandler {
          NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
              if (data) {
                  NSError *JSONError = nil;
                  NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&JSONError];
                  if (dictionary) {
                      // self.response = dictionary;  // personally, I wouldn't do this here, but just pass this back in the completion handler
                      if (completionHandler) {
                          dispatch_async(dispatch_get_main_queue(), ^{
                              completionHandler(dictionary, nil);
                          });
                      }
                  } else {
                      // NSLog(@"Serialization error: %@", JSONError.localizedDescription); // I'd let caller do whatever logging it wants
                      if (completionHandler) {
                          dispatch_async(dispatch_get_main_queue(), ^{
                              completionHandler(nil, JSONError);
                          });
                      }
                  }
              } else {
                  if (completionHandler) {
                      dispatch_async(dispatch_get_main_queue(), ^{
                          completionHandler(nil, error);
                      });
                  }
                  // NSLog(@"Error: %@", error.localizedDescription);  // I'd let caller do whatever logging it wants
              }
          }];
      
          [task resume];
      }
      

      【讨论】:

      • 正是我想要的,我已经用正确的方式编辑了原始帖子以供将来参考。
      猜你喜欢
      • 1970-01-01
      • 2011-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-12
      • 1970-01-01
      • 2018-09-24
      • 1970-01-01
      相关资源
      最近更新 更多