【问题标题】:In XCTest: how to test that a function forced execution onto main thread在 XCTest 中:如何测试函数是否强制执行到主线程
【发布时间】:2020-11-15 17:51:34
【问题描述】:

在 UI 类中,我有一个访问 UI 元素的方法,因此应该强制自己进入主线程。这是我的意思的一个最小示例:

class SomeUI {

    func doWorkOnUI() {

        guard Thread.isMainThread else {

            DispatchQueue.main.async {

                self.doWorkOnUI()
            }
            return
        }

        print("Doing the work on UI and running on main thread")
    }
}

在测试中,当然测试doWorkOnUI()已经在主线程上运行的情况是没有问题的。我只是这样做:

func testWhenOnMainThread() {

    let testedObject = SomeUI()
    let expectation = XCTestExpectation(description: "Completed doWorkOnUI")

    DispatchQueue.main.async {
        testedObject.doWorkOnUI()
        expectation.fulfill()
    }

    wait(for: [expectation], timeout: 10.0)

    // Proceed to some validation
}

即:强制执行到主线程。等待它完成。做一些检查。

但是如何测试相反的情况,即确保函数在从后台线程调用时强制自己在主线程上运行?

例如,如果我执行以下操作:

...
    DispatchQueue.global(qos: .background).async {
        testedObject.doWorkOnUI()
        expectation.fulfill()
    }
...

我刚刚测试了该函数是从后台线程执行的。但我没有明确检查它是否在主线程上运行。当然,由于此函数访问 UI 元素,因此如果不强制在主线程上,预期它会崩溃。那么“没有崩溃”是这里唯一可测试的条件吗?有没有更好的?

【问题讨论】:

    标签: swift multithreading xctest


    【解决方案1】:

    当后台有外闭包,主线程有内闭包时,我们需要两个测试:

    1. 调用外部闭包。等待期望。等待 0.01 秒。检查是否执行了预期的工作。
    2. 调用外部闭包。这一次,不要等待期望。检查工作是否未执行。

    要使用这种模式,我认为您必须更改代码,以便测试可以直接调用外部闭包,而无需进行异步舞蹈。这表明您的设计太深而无法在不进行一些更改的情况下进行测试。

    找到一种方法让中间对象捕获闭包。也就是说,不要直接调用DispatchQueue.global(qos: .background).async,而是创建一个表示此操作的类型。然后,Test Spy 版本可以捕获闭包而不是将其分派到后台,以便您的测试可以直接调用它。 然后您可以使用异步等待测试对主线程的回调。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-28
      • 1970-01-01
      • 1970-01-01
      • 2016-10-21
      相关资源
      最近更新 更多