在从XCTestCase调用的代码中使用Dispatch.main无效 [英] Using Dispatch.main in code called from XCTestCase does not work
问题描述
我有一个函数,它是一个围绕同步函数的异步包装器.
I have a function that is a async wrapper around a synchronous function.
同步功能类似于:
class Foo {
class func bar() -> [Int] {
return [1,2,3]
}
class func asyncBar(completion: @escaping ([Int]) -> Void) {
DispatchQueue.global(qos: .userInitiated).async {
let intArray = bar()
DispatchQueue.main.async {
completion(intArray)
}
}
}
}
当我从 XCTestCase
调用它时,完成
无法运行.
When I call it from a XCTestCase
completion
does not run.
在XCode中进行单元测试的方式与主线程之间是否存在某种有害的交互作用?
Is there some sort of perverse interaction between the way unit tests are done in XCode and the main thread?
我在网上找不到关于此的文档.
I can find no documentation on the Web about this.
在与Gui交互时,我必须使用主线程进行回调.
I have to use the main thread for the callback as it interacts with the Gui.
我的测试用例看起来像:
My test case looks something like:
func testAsyncBar() throws {
var run = true
func stopThisThing(ints: [Int]) {
run = false
}
Foo.asyncBar(completion: stopThisThing)
while run {
print ("Running...")
usleep(100000)
}
}
繁忙的循环永远不会停止.
The busy loop at the end never stops.
推荐答案
您的测试的 while
循环将阻塞主线程(如果测试在主线程上运行).这样,通过 DispatchQueue.main.async
调度的闭包将永远无法运行,并且您的 run
布尔值也永远不会重置.这将导致死锁.您可以通过打印 Thread.isMainThread
或添加诸如 dispatchPrecondition(condition:.onQueue(.main))
之类的测试来确认这一点.
Your test’s while
loop will block the main thread (if the test runs on the main thread). As such, the closure dispatched via DispatchQueue.main.async
can never run, and your run
Boolean will never get reset. This results in a deadlock. You can confirm this by printing Thread.isMainThread
or adding a test like dispatchPrecondition(condition: .onQueue(.main))
.
幸运的是,单元测试具有避免这种死锁的简单机制.如果希望单元测试等待某些异步过程,请使用 XCTestExpectation
:
Fortunately, unit tests have a simple mechanism that avoids this deadlock.
If you want unit test to wait for some asynchronous process, use an XCTestExpectation
:
func testAsyncBar() throws {
let e = expectation(description: "asyncBar")
func stopThisThing(ints: [Int]) {
e.fulfill()
}
Foo.asyncBar(completion: stopThisThing)
waitForExpectations(timeout: 5)
}
这避免了 while
循环所引入的问题,这些问题原本会阻塞线程.
This avoids problems introduced by the while
loop that otherwise blocked the thread.
请参见测试具有期望的异步操作.
这篇关于在从XCTestCase调用的代码中使用Dispatch.main无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!