【问题标题】:XCTest Async Function SwiftXCTest 异步函数 Swift
【发布时间】:2020-11-24 11:35:12
【问题描述】:

我是 XCTest 的新手,我已经在模型、视图、控制器中构建了我的代码

因此控制器将从模型中获取数据,一旦获取数据,控制器将更新视图。 所以我有我的控制器和视图如下

控制器:

func loadData() {
    Model.provideData { response in
        if response != nil {
            view.refresh()
        }
    }
}

查看:

func refresh() {
    isViewLoaded = true
}

这是我的 XCTest

func testLoadData() {
    let sut = Controller()
    let mockView = View()
    mockView.setController(controller: sut)
    controller.loadData()
    /** HERE is the problem, because it is a ASYNC call, i need to wait for the flag is set **/
    XCTAssertTrue(mockView.isViewLoaded, "isViewLoaded equals to true")
}

我知道我可以

let expectation = expectation(description: "wait for isViewLoaded set to true")

但是我应该把expectation.fulfill()放在哪里?

waitForExpectation(timeout: 5, handler: nil)

感谢任何帮助。谢谢

【问题讨论】:

  • 您需要模拟控制器,以便您的测试获得完成处理程序。或者让你的模型可测试。
  • 我的目标是测试控制器,我已经可以测试我的模型了

标签: swift xctest xctestcase xctestexpectation


【解决方案1】:

您需要您的loadData 有一个完成处理程序,因此能够在异步函数完成时通知其调用者。

func loadData(completion: @escaping () -> Void) {
    Model.provideData { response in
        if response != nil {
            view.refresh()
        }
        completion()
    }
}

然后在您的测试中,在 completionloadData 中执行 expectation.fulfill

func testLoadData() {
    let expectation = expectation(description: "wait for isViewLoaded set to true")
    let sut = Controller()
    let mockView = View()
    mockView.setController(controller: sut)
    controller.loadData {
        expectation.fulfill()
    }
    waitForExpectation(timeout: 5, handler: nil)
    XCTAssertTrue(mockView.isViewLoaded, "isViewLoaded equals to true")
}

【讨论】:

  • 谢谢,是的,我想过让我的 loadData 回调,只是想这是否是最佳实践?由于我对初始化测试还很陌生,我不确定是否可以?
  • 这基本上就是我在评论中所说的。 (不是批评,只是告诉 OP。)换句话说,OP,让控制器本身或模拟版本可测试是你的工作。您可以使用依赖注入,以便只有可测试版本提供回调。
  • @wes.i 是的,异步方法最好有回调。不仅仅是为了测试,而是在一般情况下。
猜你喜欢
  • 2016-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多