1

I have the following code that I'm wanting to create a unit test for. I want to check if self.response is not nil

- (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]; } 

what I have so far is

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

But of course this isn't correct. Wondering if someone could help me get the idea on how to write this test.

Thanks

0

2 Answers 2

4

Does downloadJson not provide some completion handler, a block that can be called when the asynchronous call finishes? See How do I unit test HTTP request and response using NSURLSession in iOS 7.1? for an example of how one generally uses XCTestExpectation.

Usually you put a [expectation fulfill] inside the completion handler so that the waitForExpectationsWithTimeout knows that it succeeded.

Frankly, having a completion block for your downloadJson method would probably be useful, anyway, so you might want to add that.

- (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]; } 
Sign up to request clarification or add additional context in comments.

1 Comment

exactly what I was looking for, I've edited the original post with the correct way for future reference.
2

following the link posted by Rob, I now have this and it works

- (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]; } 

and the test

- (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]; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.