我希望下面的测试通过。在我的真实代码中,AsyncClass
使用DispatchGroup
类将工作分配到多个队列。在Swift中,我们使用@escaping
完成处理程序来进行异步工作。我正在寻找一种使调用线程等待dispatchGroup
完成工作的方法。关闭可能会消失。
我仅将此代码用于测试,我知道我绝不应该在生产中阻塞主线程。
用例:我有一些调用昂贵方法的测试。在此示例中,该方法的工作方式类似于“ AsyncClass”。在AsyncClass内部,我将工作分配给某些线程以加快处理速度。现在,在测试时,我可以一直创建期望,并以闭包形式调用此方法,但这对我来说很冗长。为了方便使用,我想将异步方法转换为同步方法。
import XCTest
class DispatchGroupTestTests: XCTestCase {
func testIets() {
let clazz = AsyncClass()
var isCalled = false
clazz.doSomething {
isCalled = true
}
XCTAssert(isCalled)
}
}
class AsyncClass {
func doSomething(completionHandler: @escaping () -> ()) {
let dispatchGroup = DispatchGroup()
for _ in 0...5 {
dispatchGroup.enter()
DispatchQueue.global().async {
let _ = (0...10000).map { $0 * 1000 }
dispatchGroup.leave()
}
}
dispatchGroup.wait() // Doesn't work
dispatchGroup.notify(queue: .main) {
completionHandler()
}
}
}
答案 0 :(得分:0)
我设法做到了这一点(只需在while循环中休眠线程即可):
import XCTest
class DispatchGroupTestTests: XCTestCase {
func testIets() {
let clazz = AsyncClass()
var isCalled = false
clazz.doSomething {
isCalled = true
}
XCTAssert(isCalled)
}
}
class AsyncClass {
func doSomething(completionHandler: () -> ()) {
var isDone = false
let dispatchGroup = DispatchGroup()
for _ in 0...5 {
dispatchGroup.enter()
DispatchQueue.global().async {
let _ = (0...1000000).map { $0 * 10000 }
dispatchGroup.leave()
}
}
dispatchGroup.notify(queue: .global()) {
isDone = true
}
while !isDone {
print("sleepy")
Thread.sleep(forTimeInterval: 0.1)
}
completionHandler()
}
}
现在,不再需要闭包了,期望值可以删除(尽管我在提供的示例中没有期望值,但可以在“真实”测试代码中省略它们):
import XCTest
class DispatchGroupTestTests: XCTestCase {
var called = false
func testIets() {
let clazz = AsyncClass()
clazz.doSomething(called: &called)
XCTAssert(called)
}
}
class AsyncClass {
func doSomething(called: inout Bool) {
var isDone = false
let dispatchGroup = DispatchGroup()
for _ in 0...5 {
dispatchGroup.enter()
DispatchQueue.global().async {
let _ = (0...1000000).map { $0 * 10000 }
dispatchGroup.leave()
}
}
dispatchGroup.notify(queue: .global()) {
isDone = true
}
while !isDone {
print("sleepy")
Thread.sleep(forTimeInterval: 0.1)
}
called = true
}
}
所以我对度量值块进行了性能测试,并实现了我的期望值(不是XCTestCase期望值):与将所有工作分配给线程相比,将工作分配到其他线程并阻塞自旋锁中的调用线程更快。调用线程(考虑到我们不想转义块,我们希望所有内容都同步,只是为了在测试方法中轻松调用函数)。我只是填写随机计算,结果就是这样:
import XCTest
let work: [() -> ()] = Array.init(repeating: { let _ = (0...1000000).map { $0 * 213123 / 12323 }}, count: 10)
class DispatchGroupTestTests: XCTestCase {
func testSync() {
measure {
for workToDo in work {
workToDo()
}
}
}
func testIets() {
let clazz = AsyncClass()
measure {
clazz.doSomething()
}
}
}
class AsyncClass {
func doSomething() {
var isDone = false
let dispatchGroup = DispatchGroup()
for workToDo in work {
dispatchGroup.enter()
DispatchQueue.global().async {
workToDo()
dispatchGroup.leave()
}
}
dispatchGroup.notify(queue: .global()) {
isDone = true
}
while !isDone {
Thread.sleep(forTimeInterval: 0.1)
}
}
}