使单元测试等待另一个方法中的异步调用

Posted

技术标签:

【中文标题】使单元测试等待另一个方法中的异步调用【英文标题】:Make a unit test wait for a async call inside another method 【发布时间】:2017-06-03 12:46:10 【问题描述】:

我正在测试我的所有数据是否正确加载到 UIViewControllerUITableView

加载数据和填充表格的代码在 myMethod() 内部,它是一个异步调用。

func myMethod() 
    reloadModel  ... wait for async callback ... 

在我的测试用例中,我正在调用myMethod(),但我不知道如何等待异步调用完成。

//Test Code
func testLoadData() 
        let listVC = ListViewController.init(tableView:tableView)
        listVC .myMethod()
         ... here it should wait for the async call...
        XCTAssertEqual(...)

【问题讨论】:

这个测试无论如何都没有意义,因为你不能调用任何包含didwillshould的委托方法。框架调用这些方法来通知工作流的特定阶段。我怀疑单元测试是否存在显着差异。 @vadian 好的,让我们再具体一点。我已经更新了这个问题。假设我现在有一个随机方法 myMethod()。 没有这样的选项。您应该考虑如何抽象您的“模型提供者”类并将依赖项注入您的 viewContorller @AntonBelousov 我明白为什么方法现在是错误的了。好的,谢谢。 【参考方案1】:

问题是您尝试进行的测试过多。您对myMethod() 的测试不应断言已获取数据(您不应在单元测试中进行联网)。它应该测试视图控制器是否在其数据获取器助手上调用了正确的方法。这意味着您需要在那里创建一个接缝,然后模拟出该 fetcher 对象。

那么在您的视图控制器测试中没有等待;您只需断言 myMethod() 在模拟上触发对 pleaseGoGetMyData() 的调用。

然后你单独测试数据获取器,再次模拟它对网络堆栈的依赖,这样你只需要测试获取器是否发出正确的请求,并将正确的(虚拟)数据返回给它的客户端。

如果做不到这一点,要进行异步测试,您需要使用XCTestExpectation。示例见EridB's answer to a related question。

【讨论】:

以上是关于使单元测试等待另一个方法中的异步调用的主要内容,如果未能解决你的问题,请参考以下文章

使用 Moq 模拟单元测试的异步方法

如何对带有异步的流进行单元测试

单元测试在C#,Moq中调用SAP异步Web服务

对于异步代码的单元测试

在单元测试中同步调用异步方法是不是不正确?

Swift 单元测试 - 等待 viewDidLoad