为什么XCTest等待期望挂起异步后台任务?



我在测试中遇到了一些失败,我发现它们似乎是由XCTest期望等待暂停Task实例引起的。即使它们在后台线程上。

这是一个虚构的测试,这是我的应用程序中的代码的一个极大的简化版本(请原谅打印,这只是我胡闹试图看到排序):

func testTask() async throws {
let exp = expectation(description: "")
print("Queuing")
Task.detached(priority: .background) {
let duration = try await ContinuousClock().measure {
print("  Initialing task sleep")
try await Task.sleep(for:.seconds(1))
}
print("  Fulfilling after (duration)")
exp.fulfill()
}
print("Waiting")
wait(for: [exp], timeout: 4.0)
print("Finished")
}

现在,当我运行这个测试时,任务在后台线程上执行并按预期挂起,但是它保持挂起至少4秒,直到预期超时后才完成。

到目前为止,我所读到的一切都表明,你应该能够在任务中使用期望,但到目前为止,这对我来说并不奏效。

我错过了什么,或者我将不得不写一些等待代码像一个期望代替?

注释:这个测试是我的应用中一个情况的一个极大简化的版本。所以,虽然它可能没有意义作为一个独立的测试,它是一个准确的表示我正在测试。其中还有传统完成的概念,因为实际代码触发后台任务,然后通知其他代码何时完成。

Apple已经承认wait函数在与async/await结合使用时存在问题-根据Xcode 14.3发布说明

修正:XCTestCase.wait(for:timeout:enforceOrder:)和相关方法现在在并发Swift函数中标记不可用,因为它们可能导致测试死锁。相反,您可以使用新的并发安全的XCTestCase.fulfillment(of:timeout:enforceOrder:)方法。(91453026)

所以,如果你使用的是Xcode 14.3(或更高版本),你应该使用异步版本的满足(:超时:enforceOrder)

如果您可以从测试声明中删除async,那么wait(for:)不能工作:

waitForExpectations(timeout: 4.0)

也可以在async测试中await期望:

await waitForExpectations(timeout: 4.0)

我没有解释为什么这个工作,wait(for: [exp], timeout: 4.0)不能。

最新更新