在 XCTest 中:如何测试函数是不是强制执行到主线程
Posted
技术标签:
【中文标题】在 XCTest 中:如何测试函数是不是强制执行到主线程【英文标题】: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 元素,因此如果不强制在主线程上,预期它会崩溃。那么“没有崩溃”是这里唯一可测试的条件吗?有没有更好的?
【问题讨论】:
【参考方案1】:当后台有外闭包,主线程有内闭包时,我们需要两个测试:
-
调用外部闭包。等待期望。等待 0.01 秒。检查是否执行了预期的工作。
调用外部闭包。这一次,不要等待期望。检查工作是否未执行。
要使用这种模式,我认为您必须更改代码,以便测试可以直接调用外部闭包,而无需进行异步舞蹈。这表明您的设计太深而无法在不进行一些更改的情况下进行测试。
找到一种方法让中间对象捕获闭包。也就是说,不要直接调用DispatchQueue.global(qos: .background).async
,而是创建一个表示此操作的类型。然后,Test Spy 版本可以捕获闭包而不是将其分派到后台,以便您的测试可以直接调用它。 然后您可以使用异步等待测试对主线程的回调。
【讨论】:
以上是关于在 XCTest 中:如何测试函数是不是强制执行到主线程的主要内容,如果未能解决你的问题,请参考以下文章