I have a networking class called: ITunesAlbumDataDownloader
@implementation AlbumDataDownloader
- (void)downloadDataWithURLString:(NSString *)urlString
completionHandler:(void (^)(NSArray *, NSError *))completionHandler
{
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:urlString]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
NSArray *albumsArray = [self parseJSONData:data];
completionHandler(albumsArray, error);
}];
[dataTask resume];
}
- (NSArray *)parseJSONData:(NSData *)data {
NSMutableArray *albums = [[NSMutableArray alloc] init];
...
...
// Return the array
return [NSArray arrayWithArray:albums];
}
@end
and i need to create a Unit Test for this which does the following:
- The NSURLSession dataTaskWithRequest:completionHandler: response is mocked to contain the fake JSON data i have:
// Expected JSON response
NSData *jsonResponse = [self sampleJSONData];
- The returned array from the public method downloadDataWithURLString:completionHandler: response should contain all the albums and nil error.
Other points to bare in mind is that i need to mock NSURLSession with the fake JSON data "jsonResponse" to the downloadDataWithURLString:completionHandler: method WITHOUT invoking an actual network request.
I have tried various different things but i just can not work it out, i think its the combination of faking the request and the blocks which is really confusing me.
Here is two examples of my test method that i tried (i actually tried a lot of other ways also but this is what i have remaining right now):
- (void)testValidJSONResponseGivesAlbumsAndNilError {
// Given a valid JSON response containing albums and an AlbumDataDownloaderTests instance
// Expected JSON response
NSData *jsonResponse = [self sampleJSONDataWithAlbums];
id myMock = [OCMockObject mockForClass:[NSURLSession class]];
[[myMock expect] dataTaskWithRequest:OCMOCK_ANY
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error)
{
}];
[myMock verify];
}
and
- (void)testValidJSONResponseGivesAlbumsAndNilError {
// Given a valid JSON response containing albums and an AlbumDataDownloaderTests instance
// Expected JSON response
NSData *jsonResponse = [self sampleJSONDataWithAlbums];
id myMock = [OCMockObject mockForClass:[AlbumDataDownloader class]];
[[[myMock stub] andReturn:jsonResponse] downloadDataWithURLString:OCMOCK_ANY
completionHandler:^(NSArray *response, NSError *error)
{
}];
[myMock verify];
}
}
I have a feeling that in both instances I'm probably way off the mark :(
I would really appreciate some help with this.
Thanks.
UPDATE 1:
Here is what i have now come up with but need to know if I'm on the right track or still making a mistake?
id mockSession = [OCMockObject mockForClass:[NSURLSession class]];
id mockDataTask = [OCMockObject mockForClass:[NSURLSessionDataTask class]];
[[mockSession stub] dataTaskWithRequest:OCMOCK_ANY
completionHandler:^(NSData _Nullable data, NSURLResponse Nullable response, NSError * Nullable error)
{
NSLog(@"Response: %@", response);
}];
[[mockDataTask stub] andDo:^(NSInvocation *invocation)
{
NSLog(@"invocation: %@", invocation);
}];