gpt4 book ai didi

objective-c - 使用 NSURLSession 对 OCMock 进行单元测试

转载 作者:太空狗 更新时间:2023-10-30 03:53:54 26 4
gpt4 key购买 nike

我有一个名为: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

我需要为此创建一个单元测试,它执行以下操作:

  • NSURLSession dataTaskWithRequest:completionHandler: 响应被模拟为包含我拥有的虚假 JSON 数据:

//预期的 JSON 响应

NSData *jsonResponse = [self sampleJSONData];
  • 从公共(public)方法 downloadDataWithURLString:completionHandler:response 返回的数组应该包含所有专辑和零错误。

其他要记住的一点是,我需要使用伪造的 JSON 数据“jsonResponse”模拟 NSURLSession 到 downloadDataWithURLString:completionHandler: 方法不调用实际的网络请求

我尝试了各种不同的方法,但我就是无法解决,我认为这是伪造请求和 block 的结合,这让我很困惑。

这是我尝试过的两个测试方法示例(实际上我也尝试了很多其他方法,但这是我现在剩下的方法):

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

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

我觉得在这两种情况下我可能都离题了 :(

我非常感谢对此的一些帮助。

谢谢。

更新 1:

这是我现在想到的,但需要知道我是在正确的轨道上还是在犯错误?

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

最佳答案

block 的技巧是您需要测试来调用 block ,无论测试需要什么参数。

在 OCMock 中,可以这样做:

OCMStub([mock someMethodWithBlock:([OCMArg invokeBlockWithArgs:@"First arg", nil])]);

这很方便。但…


缺点是当 someMethodWithBlock: 被调用时,该 block 将被立即调用。这通常不能反射(reflect)生产代码的时序。

如果你想推迟调用 block 直到调用方法完成之后,然后捕获它。在 OCMock 中,可以这样做:

__block void (^capturedBlock)(id arg1);
OCMStub([mock someMethodWithBlock:[OCMArg checkWithBlock:^BOOL(id obj) {
capturedBlock = obj;
return YES;
}]]);

// ...Invoke the method that calls someMethodWithBlock:, then...
capturedBlock(@"First arg"); // Call the block with whatever you need

我更喜欢使用 OCHamcrest's HCArgumentCaptor。 OCMock 支持 OCHamcrest 匹配器,所以我相信这应该有效:

HCArgumentCaptor *argument = [[HCArgumentCaptor alloc] init];
OCMStub([mock someMethodWithBlock:argument]);

// ...Invoke the method that calls someMethodWithBlock:, then...
void (^capturedBlock)(id arg1) = argument.value; // Cast generic captured argument to specific type
capturedBlock(@"First arg"); // Call the block with whatever you need

关于objective-c - 使用 NSURLSession 对 OCMock 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33930577/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com