繁体   English   中英

在 XCTest 中:如何测试 function 强制执行到主线程

[英]In XCTest: how to test that a function forced execution onto main thread

在 UI class 中,我有一个访问 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
}

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

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

例如,如果我做类似的事情:

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM