在单元测试中使用 AFNetworking 监控可达性失败

Posted

技术标签:

【中文标题】在单元测试中使用 AFNetworking 监控可达性失败【英文标题】:Monitoring Reachability with AFNetworking in unit test fails 【发布时间】:2015-10-22 09:42:50 【问题描述】:

在我正在工作的一个项目中,我实现了HTTP Manager Reachability 示例。

当我运行实际应用程序时,它会进入块内并从那里到开关:

[manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) 
switch (status) 

另外,当我调用...reachabilityManager] isReachable 方法时,按预期返回true。

当我尝试单元测试我编写的一个使用...reachabilityManager] isReachable 作为前提条件的类方法时会出现问题 - 它返回 false 并且奇怪的是在调试期间我注意到它没有'不要进入上面的块,它会跳过它。

当然,在实际应用中,它会进入块内。

我什至尝试在单元测试中使用 OCMock 模拟实现 HTTP 管理器可达性示例的类,但它给了我相同的结果:

// NetworkClass implements the example
NetworkClass *networkClass = [[NetworkClass alloc] init];
id mockedNetworkClass = OCMPartialMock(networkClass);
// startNetworkMonitoring method implements the whole example above
[mockedNetworkClass startNetworkMonitoring];
// Giving enough time for AFNetworking to finish
[NSThread sleepForTimeInterval:60.0f];

EDIT1:

看起来信号量/XCTestExpectation 没有帮助,问题出在 AFNetworkReachabilityManager::startMonitoring:

获得所需回调的唯一方法是在 startMonitoring 方法中 dispatch_async(dispatch_get_main_queue(), ^ callback(status);

但即使我们使用前面提到的信号量/XCTestExpectation,它也会在单元测试之外运行。

仍在寻找灵魂..

EDIT2:

我试图关注objc.io 的测试异步代码,但它似乎缺少一些代码,并且一些解释缺少集成细节。

【问题讨论】:

我不确定您要测试什么,但也许您可以捕获状态更改块并针对不同的测试用例使用不同的参数执行它。这对你有意义吗? 其实没有。正如我所写,我正在尝试测试一个正在做某事的方法,但该方法的前提是 isReachable 方法,这就是问题所在。 如果你模拟 manager.reachabilityManager 并存根 isReachable 方法以始终返回 YES 会怎样。这将允许您进行测试。请注意,通过实际使用 Reachability 对象,您将在测试中引入依赖项。 问题是OCMock不能返回原语。 OCMockito 可以,但不允许部分模拟。我仍在寻找可以结合这两个功能的解决方案。 【参考方案1】:

我认为休眠线程会导致问题。

尝试使用 Writing Tests of Asynchronous Operations 中记录的期望 API。

与此类似的内容应该可以帮助您入门(请注意,这更多是对期望 API 的演示,而不是完整的工作测试用例):

- (void)testReachability 
    XCTestExpectation *expectation = [self expectationWithDescription:@"Wait for reachability"];

    [manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) 
        ...

        [expectation fulfill];

    ];

    [self waitForExpectationsWithTimeout:10 handler:^(NSError * _Nullable error) 
        // timed out waiting for reachability
    ];

【讨论】:

感谢回复。我试过了,但失败了。另外,我尝试使用与 XCTestExpectation 相同的信号量,但它也失败了。它永远不会进入块 - 请记住,在调试期间,我已经观察了 basicNetwork 对象,并且它已使用正确的 URL 完全初始化。 我认为我发现了问题,在运行实际应用程序时,第一次调用到达 setReachabilityStatusChangeBlock 不要进入块,仅在第二次调用时(这是 AFNetworking 的回调)它进入块内。所以现在的问题是如何在单元测试实际上是同步的时候启用这个回调(在单元测试内部)......

以上是关于在单元测试中使用 AFNetworking 监控可达性失败的主要内容,如果未能解决你的问题,请参考以下文章

AFNetworking 单元测试

仅在提供的控制器上使用 AFNetworking 监控可达性

信号量等待导致 AFNetworking 阻塞?

在 UITableViewCell 中,UIImageView 内容在使用 AFNetworking 的某些单元格之后重复

4Go语言单元测试性能测试与监控

4Go语言单元测试性能测试与监控